Skip to contentSkip to conversation

eal: add option to put timestamp on console output

PATCH In review Stephen Hemminger 12 participants 486 messages Aug 14, 2020 – Nov 8, 2024 Arm/Amlogic Meson SoC support Page 4 of 5

lore
Share & tools
lore
#322 lore raw

PATCH v23 13/15 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  15 +++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   4 +-
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 200 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |  16 +++
 lib/log/meson.build                 |   4 +
 lib/log/version.map                 |   1 +
 9 files changed, 258 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_journal.c
doc/guides/prog_guide/log_lib.rst +14 -0
index abaedc7212..476dedb097 100644
@@ -100,6 +100,20 @@ option. There are three possible settings for this option:
 
 If ``--syslog`` option is not specified, then only console (stderr) will be used.
 
+Messages can be redirected to systemd journal which is an enhanced version of syslog with the ``--log-journal`` option.
+
+There are three possible settings for this option:
+
+*auto*
+    If stderr is redirected to journal by ``systemd`` service
+    then use journal socket to instead of stderr for log.
+    This is the default.
+
+*never*
+    Do not try to use journal.
+
+*always*
+    Always try to direct messages to journal socket.
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +15 -0
index 8d5a83d871..53857b5f5c 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
@@ -1617,6 +1618,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
@@ -1845,6 +1847,16 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+	case OPT_LOG_JOURNAL_NUM:
+		if (eal_log_journal(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_JOURNAL);
+			return -1;
+		}
+		break;
+#endif
+
 	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
@@ -2222,6 +2234,9 @@ eal_common_usage(void)
 	       "  --"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
+#ifdef RTE_EXEC_ENV_LINUX
+	       "  --"OPT_LOG_JOURNAL"[=<when>]  Enable use of systemd journal\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..c5a1c70288 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_JOURNAL       "log-journal"
+	OPT_LOG_JOURNAL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +3 -1
index f748551bc0..96fa651e81 100644
@@ -511,7 +511,9 @@ eal_log_init(const char *id)
 	is_terminal = isatty(STDERR_FILENO);
 #endif
 
-	if (log_syslog_enabled(is_terminal))
+	if (log_journal_enabled())
+		log_journal_open(id);
+	else 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;
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +200 -0

200 lines not on this page · raw message

lib/log/log_private.h +16 -0
index 532a481340..d8602681b2 100644
@@ -34,4 +34,20 @@ bool log_syslog_enabled(bool is_tty);
 void log_syslog_open(const char *id, bool is_terminal);
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+bool log_journal_enabled(void);
+void log_journal_open(const char *id);
+#else
+static inline bool
+log_journal_enabled(void)
+{
+	return false;
+}
+
+static inline void
+log_journal_open(const char *id __rte_unused)
+{
+}
+#endif /* !RTE_EXEC_ENV_LINUX */
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +4 -0
index 4ac232786e..86e4452b19 100644
@@ -11,4 +11,8 @@ if not is_windows
     sources += files('log_syslog.c')
 endif
 
+if is_linux
+    sources += files('log_journal.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 8be6907840..800d3943bc 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.45.2
#323 lore raw

PATCH v23 14/15 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

---
 app/test/test_eal_flags.c           |  24 +++++
 doc/guides/prog_guide/log_lib.rst   |  15 +++
 lib/eal/common/eal_common_options.c |  11 +++
 lib/eal/common/eal_options.h        |   6 +-
 lib/log/log.c                       |  19 ++--
 lib/log/log_color.c                 | 148 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 230 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index 06295030b2..6ee56ec97a 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +15 -0
index 476dedb097..647c3fc28a 100644
@@ -59,6 +59,21 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+he optional argument ``when`` can be ``auto``, ``never``, or ``always``.
+The default setting is ``auto`` which enables color when the output to
+``stderr`` is a terminal.
+If the ``when`` argument is omitted, it defaults to ``always``.
+
+For example to turn off all coloring::
+
+	/path/to/app --log-color=none
+
+
 Log timestamp
 ~~~~~~~~~~~~~
 
lib/eal/common/eal_common_options.c +11 -0
index 53857b5f5c..271db58a30 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1874,6 +1876,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2243,6 +2253,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +4 -2
index c5a1c70288..c0686c2544 100644
@@ -33,10 +33,12 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
-#define OPT_LOG_LEVEL         "log-level"
-	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_JOURNAL       "log-journal"
 	OPT_LOG_JOURNAL_NUM,
+#define OPT_LOG_LEVEL         "log-level"
+	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +13 -6
index 96fa651e81..8b7b394f49 100644
@@ -511,14 +511,21 @@ eal_log_init(const char *id)
 	is_terminal = isatty(STDERR_FILENO);
 #endif
 
-	if (log_journal_enabled())
+	if (log_journal_enabled()) {
 		log_journal_open(id);
-	else if (log_syslog_enabled(is_terminal))
+	} else 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;
+	} else if (log_timestamp_enabled()) {
+		if (log_color_enabled(is_terminal))
+			rte_logs.print_func = color_print_with_timestamp;
+		else
+			rte_logs.print_func = log_print_with_timestamp;
+	} else {
+		if (log_color_enabled(is_terminal))
+			rte_logs.print_func = color_print;
+		else
+			rte_logs.print_func = vfprintf;
+	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
lib/log/log_color.c new file +148 -0

148 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index d8602681b2..855e32db90 100644
@@ -50,4 +50,12 @@ log_journal_open(const char *id __rte_unused)
 }
 #endif /* !RTE_EXEC_ENV_LINUX */
 
+bool log_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 86e4452b19..b3de57b9c7 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -0
index 800d3943bc..09d8a4289b 100644
@@ -25,6 +25,7 @@ DPDK_25 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
Signature · 1 line
2.45.2
Acked-by on v23 14/15
#324 lore raw

Re: [PATCH v23 14/15] log: colorize log output

Quoted 7 lines · Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

#325 lore raw

PATCH v23 15/15 doc: add release note about log library

In reply to Stephen Hemminger

Significant enough to add some documentation.

---
 doc/guides/rel_notes/release_24_11.rst | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
doc/guides/rel_notes/release_24_11.rst +15 -0
index 0ff70d9057..8878ed33aa 100644
@@ -55,6 +55,21 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Enhancements to logging library.**
+
+  * The log is initialized earlier in startup so all messages go through the library.
+
+  * An option is added to timestamp log messages, which is useful for debugging delays in
+    application and driver startup.
+
+  * Log messages are now in color if going to a terminal (similar to dmesg).
+    The default format shows timestamp in green, subsystem in yellow,
+    and the message is bold, boldface or normal depending on severity.
+
+  * If the application is a systemd service and the log output is being
+    sent of standard error then DPDK will switch to journal native protocol.
+
+  * On FreeBSD the log library can syslog the same as Linux.
 
 Removed Items
 -------------
Signature · 1 line
2.45.2
Acked-by on v23 15/15
#326 lore raw

Re: [PATCH v23 15/15] doc: add release note about log library

Quoted 34 lines · Stephen Hemminger

Significant enough to add some documentation.

---
 doc/guides/rel_notes/release_24_11.rst | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
doc/guides/rel_notes/release_24_11.rst +15 -0
index 0ff70d9057..8878ed33aa 100644
@@ -55,6 +55,21 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Enhancements to logging library.**
+
+  * The log is initialized earlier in startup so all messages go through the library.
+
+  * An option is added to timestamp log messages, which is useful for debugging delays in
+    application and driver startup.
+
+  * Log messages are now in color if going to a terminal (similar to dmesg).
+    The default format shows timestamp in green, subsystem in yellow,
+    and the message is bold, boldface or normal depending on severity.
+
+  * If the application is a systemd service and the log output is being
+    sent of standard error then DPDK will switch to journal native protocol.
+
+  * On FreeBSD the log library can syslog the same as Linux.
 
 Removed Items
 -------------
#327 lore raw

Re: [PATCH v23 00/15] Logging improvements

In reply to Stephen Hemminger
Quoted 38 lines · Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

v23 - simplify and fix Windows and FreeBSD builds; fix #ifdefs.
Change from defining stubs to using inline functions in log_private.h.

Quoted 17 lines

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

Thanks for the cleanup.

#328 lore raw

v24 cover Logging enhancements for 24.11

In reply to Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

v24 - incorporate a couple of small review feedback items.
expand the release note.

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  64 +++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 ---
 doc/guides/prog_guide/log_lib.rst             |  72 ++++++
 doc/guides/rel_notes/release_24_11.rst        |  27 +++
 lib/eal/common/eal_common_debug.c             |   6 +-
 lib/eal/common/eal_common_options.c           | 135 ++++++-----
 lib/eal/common/eal_options.h                  |   7 +
 lib/eal/freebsd/eal.c                         |  64 ++----
 lib/eal/linux/eal.c                           |  68 ++----
 lib/eal/windows/eal.c                         |  49 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  71 +++---
 lib/log/log_color.c                           | 148 ++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 ++-
 lib/log/log_journal.c                         | 200 +++++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  61 +++++
 lib/log/log_syslog.c                          |  88 ++++++++
 lib/log/log_timestamp.c                       | 210 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  12 +-
 lib/log/version.map                           |   5 +-
 26 files changed, 1099 insertions(+), 376 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.45.2
#329 lore raw

PATCH v24 1/15 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index c5a703b5c0..ecf6f955cc 100644
@@ -185,6 +185,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.45.2
#330 lore raw

PATCH v24 2/15 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.45.2
#331 lore raw

PATCH v24 3/15 windows: add os shim for localtime_r

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..665c9ac93b 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timep, struct tm *result)
+{
+	if (localtime_s(result, timep) == 0)
+		return result;
+	else
+		return NULL;
+}
+#define localtime_r(timep, result) rte_localtime_r(timep, result)
+
 #endif /* _RTE_OS_SHIM_ */
Signature · 1 line
2.45.2
Acked-by on v24 3/15
#332 lore raw

Re: [PATCH v24 03/15] windows: add os shim for localtime_r

Quoted 30 lines · Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..665c9ac93b 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timep, struct tm *result)
+{
+	if (localtime_s(result, timep) == 0)
+		return result;
+	else
+		return NULL;
+}
+#define localtime_r(timep, result) rte_localtime_r(timep, result)
+
 #endif /* _RTE_OS_SHIM_ */
#333 lore raw

PATCH v24 4/15 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 40 +++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 -----------------------------
 lib/eal/linux/eal.c                 | 39 ---------------------------
 lib/eal/windows/eal.c               | 35 ------------------------
 5 files changed, 41 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +40 -0
index f1a5e329a5..eb079a65a9 100644
@@ -1640,6 +1640,46 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		}
+	}
+
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index d742cc98e2..0ded386472 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 28b78a95a6..a77e590a72 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.45.2
#334 lore raw

PATCH v24 5/15 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index 0ded386472..7c26393d00 100644
@@ -840,8 +840,7 @@ static int rte_eal_vfio_setup(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
Signature · 1 line
2.45.2
#335 lore raw

PATCH v24 6/15 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
lib/eal/common/eal_common_debug.c +2 -4
index 3e77995896..bcfcd6df6f 100644
@@ -36,15 +36,13 @@ rte_exit(int exit_code, const char *format, ...)
 	va_list ap;
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
 	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
 	va_end(ap);
 
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.45.2
Acked-by on v24 6/15
#336 lore raw

Re: [PATCH v24 06/15] eal: change rte_exit() output to match rte_log()

Quoted 41 lines · Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
lib/eal/common/eal_common_debug.c +2 -4
index 3e77995896..bcfcd6df6f 100644
@@ -36,15 +36,13 @@ rte_exit(int exit_code, const char *format, ...)
 	va_list ap;
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
 	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
 	va_end(ap);
 
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
#337 lore raw

PATCH v24 7/15 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also allows for changes to what syslog flag means in later steps.

---
 lib/eal/common/eal_common_options.c | 51 ++---------------------------
 lib/eal/freebsd/eal.c               |  5 ++-
 lib/eal/linux/eal.c                 |  7 ++--
 lib/eal/windows/eal.c               |  6 ++--
 lib/log/log.c                       |  2 ++
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 ++-
 lib/log/log_linux.c                 | 47 ++++++++++++++++++++++++--
 lib/log/log_windows.c               |  8 ++++-
 lib/log/version.map                 |  1 +
 10 files changed, 70 insertions(+), 64 deletions(-)
lib/eal/common/eal_common_options.c +2 -49
index eb079a65a9..918cc013fe 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -349,10 +346,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1290,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1615,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1877,7 +1830,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/freebsd/eal.c +2 -3
index 7b974608e4..a609d40ee0 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index 7c26393d00..5aedd348d1 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1113,8 +1113,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index a77e590a72..69a8fc8d80 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -250,7 +250,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 255f757d94..4b24e145b6 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c +45 -2

72 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/version.map +1 -0
index 19d7f9cdb6..879567ba15 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#338 lore raw

PATCH v24 8/15 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_linux.c    | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index a609d40ee0..118c1f593b 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -572,9 +581,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 5aedd348d1..fab633976d 100644
@@ -936,6 +936,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -959,9 +968,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1113,13 +1119,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index 69a8fc8d80..c9648b7da7 100644
@@ -250,9 +250,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_linux.c +6 -8
index 47aa074da2..6d7dc8f3ab 100644
@@ -87,18 +87,16 @@ static cookie_io_functions_t console_log_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", console_log_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.45.2
#339 lore raw

PATCH v24 9/15 log: drop syslog support, and make code common

In reply to Stephen Hemminger

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

---
 app/test/test_eal_flags.c           |  11 ++-
 lib/eal/common/eal_common_options.c |   3 -
 lib/log/log.c                       |  41 +++++------
 lib/log/log_freebsd.c               |  11 ---
 lib/log/log_internal.h              |   6 --
 lib/log/log_linux.c                 | 102 ----------------------------
 lib/log/log_windows.c               |  22 ------
 lib/log/meson.build                 |   5 +-
 lib/log/version.map                 |   1 -
 9 files changed, 23 insertions(+), 179 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +5 -6
index 71d8dba731..a5c0c67357 100644
@@ -984,11 +984,10 @@ test_misc_flags(void)
 	const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+	/* With empty --syslog */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
 	/* With invalid --syslog */
 	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
@@ -1083,8 +1082,8 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not with --syslog always flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
lib/eal/common/eal_common_options.c +0 -3
index 918cc013fe..ea45c79d5c 100644
@@ -2206,9 +2206,6 @@ 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"            Set syslog facility\n"
-#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -24

73 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_linux.c deleted +0 -102

102 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/meson.build +1 -4
index 0d4319b36f..891f77a237 100644
@@ -2,8 +2,5 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files(
-        'log.c',
-        'log_' + exec_env + '.c',
-)
+sources = files('log.c')
 headers = files('rte_log.h')
lib/log/version.map +0 -1
index 879567ba15..a0341196d4 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
 	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#340 lore raw

PATCH v24 10/15 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c         | 6 +++++-
 lib/log/log_private.h | 9 +++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_private.h
lib/log/log.c +5 -1
index 3fe86ddcd7..48543ee941 100644
@@ -18,6 +18,7 @@
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -33,11 +34,13 @@ static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = vfprintf,
 };
 
 struct rte_eal_opt_loglevel {
@@ -74,6 +77,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = vfprintf;
 	return 0;
 }
 
@@ -470,7 +474,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, format, ap);
 	fflush(f);
 	return ret;
 }
lib/log/log_private.h new file +9 -0
new file mode 100644
index 0000000000..67d2463b2f
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Note: same as vfprintf() */
+typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
+
+#endif /* LOG_PRIVATE_H */
Signature · 1 line
2.45.2
#341 lore raw

PATCH v24 11/15 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 ++++
 doc/guides/prog_guide/log_lib.rst   |  26 ++++
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |   7 +-
 lib/log/log_internal.h              |   9 ++
 lib/log/log_private.h               |  11 ++
 lib/log/log_timestamp.c             | 210 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   6 +-
 lib/log/version.map                 |   1 +
 13 files changed, 318 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index a5c0c67357..40dd288d5f 100644
@@ -1054,6 +1054,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1161,6 +1174,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +26 -0
index ff9d1b54a2..504eefe1d2 100644
@@ -59,6 +59,32 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +12 -2
index ea45c79d5c..ec3b5c3dfd 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1616,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1838,7 +1840,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1846,7 +1848,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2210,6 +2219,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 118c1f593b..06bccbd026 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index fab633976d..ceaa1f9487 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index c9648b7da7..0fda2abb97 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +6 -1
index 48543ee941..6ab856272c 100644
@@ -21,7 +21,7 @@
 #include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
 struct rte_log_dynamic_type {
@@ -509,6 +509,11 @@ eal_log_syslog(const char *mode __rte_unused)
 void
 eal_log_init(const char *id __rte_unused)
 {
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = vfprintf;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +11 -0
index 67d2463b2f..67cfe72fc6 100644
@@ -3,7 +3,18 @@
 #ifndef LOG_PRIVATE_H
 #define LOG_PRIVATE_H
 
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
 /* Note: same as vfprintf() */
 typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
 
+bool log_timestamp_enabled(void);
+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);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +210 -0

210 lines not on this page · raw message

lib/log/meson.build +5 -1
index 891f77a237..04235f6ee5 100644
@@ -2,5 +2,9 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files('log.c')
+sources = files(
+        'log.c',
+        'log_timestamp.c',
+)
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index a0341196d4..155f8b3bbe 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog;
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#342 lore raw

PATCH v24 12/15 log: add optional support of syslog

In reply to Stephen Hemminger

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.

---
 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                         | 17 ++++
 lib/log/log_syslog.c                          | 88 +++++++++++++++++++
 lib/log/meson.build                           |  4 +
 lib/log/version.map                           |  2 +-
 9 files changed, 150 insertions(+), 43 deletions(-)
 create mode 100644 lib/log/log_syslog.c
app/test/test_eal_flags.c +3 -2
index 40dd288d5f..06295030b2 100644
@@ -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};
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -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
doc/guides/prog_guide/log_lib.rst +17 -0
index 504eefe1d2..abaedc7212 100644
@@ -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
lib/eal/common/eal_common_options.c +4 -1
index ec3b5c3dfd..ac1aadbef4 100644
@@ -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"
lib/log/log.c +16 -12
index 6ab856272c..f748551bc0 100644
@@ -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;
lib/log/log_private.h +17 -0
index 67cfe72fc6..532a481340 100644
@@ -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 */
lib/log/log_syslog.c new file +88 -0

88 lines not on this page · raw message

lib/log/meson.build +4 -0
index 04235f6ee5..4ac232786e 100644
@@ -7,4 +7,8 @@ sources = files(
         'log_timestamp.c',
 )
 
+if not is_windows
+    sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -1
index 155f8b3bbe..8be6907840 100644
@@ -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;
 };
Signature · 1 line
2.45.2
#343 lore raw

PATCH v24 13/15 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  15 +++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   4 +-
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 200 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |  16 +++
 lib/log/meson.build                 |   4 +
 lib/log/version.map                 |   1 +
 9 files changed, 258 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_journal.c
doc/guides/prog_guide/log_lib.rst +14 -0
index abaedc7212..476dedb097 100644
@@ -100,6 +100,20 @@ option. There are three possible settings for this option:
 
 If ``--syslog`` option is not specified, then only console (stderr) will be used.
 
+Messages can be redirected to systemd journal which is an enhanced version of syslog with the ``--log-journal`` option.
+
+There are three possible settings for this option:
+
+*auto*
+    If stderr is redirected to journal by ``systemd`` service
+    then use journal socket to instead of stderr for log.
+    This is the default.
+
+*never*
+    Do not try to use journal.
+
+*always*
+    Always try to direct messages to journal socket.
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +15 -0
index ac1aadbef4..6184d27ad3 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
@@ -1617,6 +1618,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
@@ -1840,6 +1842,16 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+	case OPT_LOG_JOURNAL_NUM:
+		if (eal_log_journal(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_JOURNAL);
+			return -1;
+		}
+		break;
+#endif
+
 	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
@@ -2217,6 +2229,9 @@ eal_common_usage(void)
 	       "  --"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
+#ifdef RTE_EXEC_ENV_LINUX
+	       "  --"OPT_LOG_JOURNAL"[=<when>]  Enable use of systemd journal\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..c5a1c70288 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_JOURNAL       "log-journal"
+	OPT_LOG_JOURNAL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +3 -1
index f748551bc0..96fa651e81 100644
@@ -511,7 +511,9 @@ eal_log_init(const char *id)
 	is_terminal = isatty(STDERR_FILENO);
 #endif
 
-	if (log_syslog_enabled(is_terminal))
+	if (log_journal_enabled())
+		log_journal_open(id);
+	else 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;
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +200 -0

200 lines not on this page · raw message

lib/log/log_private.h +16 -0
index 532a481340..d8602681b2 100644
@@ -34,4 +34,20 @@ bool log_syslog_enabled(bool is_tty);
 void log_syslog_open(const char *id, bool is_terminal);
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+bool log_journal_enabled(void);
+void log_journal_open(const char *id);
+#else
+static inline bool
+log_journal_enabled(void)
+{
+	return false;
+}
+
+static inline void
+log_journal_open(const char *id __rte_unused)
+{
+}
+#endif /* !RTE_EXEC_ENV_LINUX */
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +4 -0
index 4ac232786e..86e4452b19 100644
@@ -11,4 +11,8 @@ if not is_windows
     sources += files('log_syslog.c')
 endif
 
+if is_linux
+    sources += files('log_journal.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 8be6907840..800d3943bc 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.45.2
#344 lore raw

PATCH v24 14/15 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

---
 app/test/test_eal_flags.c           |  24 +++++
 doc/guides/prog_guide/log_lib.rst   |  15 +++
 lib/eal/common/eal_common_options.c |  11 +++
 lib/eal/common/eal_options.h        |   6 +-
 lib/log/log.c                       |  19 ++--
 lib/log/log_color.c                 | 148 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 230 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index 06295030b2..6ee56ec97a 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +15 -0
index 476dedb097..647c3fc28a 100644
@@ -59,6 +59,21 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+he optional argument ``when`` can be ``auto``, ``never``, or ``always``.
+The default setting is ``auto`` which enables color when the output to
+``stderr`` is a terminal.
+If the ``when`` argument is omitted, it defaults to ``always``.
+
+For example to turn off all coloring::
+
+	/path/to/app --log-color=none
+
+
 Log timestamp
 ~~~~~~~~~~~~~
 
lib/eal/common/eal_common_options.c +11 -0
index 6184d27ad3..de19b1c258 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1869,6 +1871,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2238,6 +2248,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +4 -2
index c5a1c70288..c0686c2544 100644
@@ -33,10 +33,12 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
-#define OPT_LOG_LEVEL         "log-level"
-	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_JOURNAL       "log-journal"
 	OPT_LOG_JOURNAL_NUM,
+#define OPT_LOG_LEVEL         "log-level"
+	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +13 -6
index 96fa651e81..8b7b394f49 100644
@@ -511,14 +511,21 @@ eal_log_init(const char *id)
 	is_terminal = isatty(STDERR_FILENO);
 #endif
 
-	if (log_journal_enabled())
+	if (log_journal_enabled()) {
 		log_journal_open(id);
-	else if (log_syslog_enabled(is_terminal))
+	} else 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;
+	} else if (log_timestamp_enabled()) {
+		if (log_color_enabled(is_terminal))
+			rte_logs.print_func = color_print_with_timestamp;
+		else
+			rte_logs.print_func = log_print_with_timestamp;
+	} else {
+		if (log_color_enabled(is_terminal))
+			rte_logs.print_func = color_print;
+		else
+			rte_logs.print_func = vfprintf;
+	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
lib/log/log_color.c new file +148 -0

148 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index d8602681b2..855e32db90 100644
@@ -50,4 +50,12 @@ log_journal_open(const char *id __rte_unused)
 }
 #endif /* !RTE_EXEC_ENV_LINUX */
 
+bool log_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 86e4452b19..b3de57b9c7 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -0
index 800d3943bc..09d8a4289b 100644
@@ -25,6 +25,7 @@ DPDK_25 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
Signature · 1 line
2.45.2
#345 lore raw

PATCH v24 15/15 doc: add release note about log library

In reply to Stephen Hemminger

Significant enough to add some documentation.

---
 doc/guides/rel_notes/release_24_11.rst | 27 ++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
doc/guides/rel_notes/release_24_11.rst +27 -0
index 0ff70d9057..d6fb6c137b 100644
@@ -55,6 +55,33 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Enhancements to logging library.**
+
+  * Syslog related changes
+
+    * The meaning of the *--syslog* option has changed.
+      Use of syslog is controlled by the *--syslog* option.
+      The default is now *auto* which uses syslog only if stderr
+      is not a terminal device.
+
+    * The syslog facility is now set to **LOG_USER** if stderr is a terminal
+      and **LOG_DAEMON** otherwise.
+
+    * Syslog is now supported on FreeBSD (but not on Windows).
+
+  * The log is initialized earlier in startup so all messages go through
+    the library.
+
+  * Added a new option to timestamp log messages, which is useful for
+    debugging delays in application and driver startup.
+
+  * Log messages are now in color if going to a terminal (similar to dmesg).
+    The default format shows timestamp in green, subsystem in yellow,
+    and the message is bold, boldface or normal depending on severity.
+
+  * If the application is a systemd service and the log output is being
+    sent of standard error then DPDK will switch to journal native protocol.
+
 
 Removed Items
 -------------
Signature · 1 line
2.45.2
#346 lore raw

v25 cover Logging enhancements for 24.11

In reply to Stephen Hemminger

mprovements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

v25 - make the delta and relative time stamp formats thread safe.
Use atomic 64 bit value (nanoseconds) and convert to timespec.

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  64 ++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 --
 doc/guides/prog_guide/log_lib.rst             |  72 ++++++
 doc/guides/rel_notes/release_24_11.rst        |  27 ++
 lib/eal/common/eal_common_debug.c             |   6 +-
 lib/eal/common/eal_common_options.c           | 135 ++++++----
 lib/eal/common/eal_internal_cfg.h             |   1 -
 lib/eal/common/eal_options.h                  |   7 +
 lib/eal/freebsd/eal.c                         |  64 +----
 lib/eal/linux/eal.c                           |  68 +----
 lib/eal/windows/eal.c                         |  49 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  71 ++++--
 lib/log/log_color.c                           | 148 +++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 +-
 lib/log/log_journal.c                         | 200 +++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  61 +++++
 lib/log/log_syslog.c                          |  88 +++++++
 lib/log/log_timestamp.c                       | 240 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  12 +-
 lib/log/version.map                           |   5 +-
 27 files changed, 1129 insertions(+), 377 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.45.2
#347 lore raw

PATCH v25 1/15 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index c5a703b5c0..ecf6f955cc 100644
@@ -185,6 +185,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.45.2
#348 lore raw

PATCH v25 2/15 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.45.2
#349 lore raw

PATCH v25 3/15 windows: add os shim for localtime_r

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..665c9ac93b 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timep, struct tm *result)
+{
+	if (localtime_s(result, timep) == 0)
+		return result;
+	else
+		return NULL;
+}
+#define localtime_r(timep, result) rte_localtime_r(timep, result)
+
 #endif /* _RTE_OS_SHIM_ */
Signature · 1 line
2.45.2
#350 lore raw

PATCH v25 4/15 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 40 +++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 -----------------------------
 lib/eal/linux/eal.c                 | 39 ---------------------------
 lib/eal/windows/eal.c               | 35 ------------------------
 5 files changed, 41 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +40 -0
index f1a5e329a5..eb079a65a9 100644
@@ -1640,6 +1640,46 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		}
+	}
+
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index d742cc98e2..0ded386472 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 28b78a95a6..a77e590a72 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.45.2
#351 lore raw

PATCH v25 5/15 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index 0ded386472..7c26393d00 100644
@@ -840,8 +840,7 @@ static int rte_eal_vfio_setup(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
Signature · 1 line
2.45.2
#352 lore raw

PATCH v25 6/15 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
lib/eal/common/eal_common_debug.c +2 -4
index 3e77995896..bcfcd6df6f 100644
@@ -36,15 +36,13 @@ rte_exit(int exit_code, const char *format, ...)
 	va_list ap;
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
 	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
 	va_end(ap);
 
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.45.2
#353 lore raw

PATCH v25 7/15 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also allows for changes to what syslog flag means in later steps.

---
 lib/eal/common/eal_common_options.c | 51 ++---------------------------
 lib/eal/common/eal_internal_cfg.h   |  1 -
 lib/eal/freebsd/eal.c               |  5 ++-
 lib/eal/linux/eal.c                 |  7 ++--
 lib/eal/windows/eal.c               |  6 ++--
 lib/log/log.c                       |  2 ++
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 ++-
 lib/log/log_linux.c                 | 47 ++++++++++++++++++++++++--
 lib/log/log_windows.c               |  8 ++++-
 lib/log/version.map                 |  1 +
 11 files changed, 70 insertions(+), 65 deletions(-)
lib/eal/common/eal_common_options.c +2 -49
index eb079a65a9..918cc013fe 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -349,10 +346,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1290,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1615,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1877,7 +1830,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/common/eal_internal_cfg.h +0 -1
index 167ec501fa..f53ab8b4aa 100644
@@ -84,7 +84,6 @@ struct internal_config {
 	/**< true if storing all pages within single files (per-page-size,
 	 * per-node) non-legacy mode only.
 	 */
-	volatile int syslog_facility;	  /**< facility passed to openlog() */
 	/** default interrupt mode for VFIO */
 	volatile enum rte_intr_mode vfio_intr_mode;
 	/** the shared VF token for VFIO-PCI bound PF and VFs devices */
lib/eal/freebsd/eal.c +2 -3
index 7b974608e4..a609d40ee0 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index 7c26393d00..5aedd348d1 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1113,8 +1113,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index a77e590a72..69a8fc8d80 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -250,7 +250,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 255f757d94..4b24e145b6 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c +45 -2

72 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/version.map +1 -0
index 19d7f9cdb6..879567ba15 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#354 lore raw

PATCH v25 8/15 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_linux.c    | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index a609d40ee0..118c1f593b 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -572,9 +581,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 5aedd348d1..fab633976d 100644
@@ -936,6 +936,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -959,9 +968,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1113,13 +1119,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index 69a8fc8d80..c9648b7da7 100644
@@ -250,9 +250,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_linux.c +6 -8
index 47aa074da2..6d7dc8f3ab 100644
@@ -87,18 +87,16 @@ static cookie_io_functions_t console_log_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", console_log_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.45.2
#355 lore raw

PATCH v25 9/15 log: drop syslog support, and make code common

In reply to Stephen Hemminger

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

---
 app/test/test_eal_flags.c           |  11 ++-
 lib/eal/common/eal_common_options.c |   3 -
 lib/log/log.c                       |  41 +++++------
 lib/log/log_freebsd.c               |  11 ---
 lib/log/log_internal.h              |   6 --
 lib/log/log_linux.c                 | 102 ----------------------------
 lib/log/log_windows.c               |  22 ------
 lib/log/meson.build                 |   5 +-
 lib/log/version.map                 |   1 -
 9 files changed, 23 insertions(+), 179 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +5 -6
index 71d8dba731..a5c0c67357 100644
@@ -984,11 +984,10 @@ test_misc_flags(void)
 	const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+	/* With empty --syslog */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
 	/* With invalid --syslog */
 	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
@@ -1083,8 +1082,8 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not with --syslog always flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
lib/eal/common/eal_common_options.c +0 -3
index 918cc013fe..ea45c79d5c 100644
@@ -2206,9 +2206,6 @@ 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"            Set syslog facility\n"
-#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -24

73 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_linux.c deleted +0 -102

102 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/meson.build +1 -4
index 0d4319b36f..891f77a237 100644
@@ -2,8 +2,5 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files(
-        'log.c',
-        'log_' + exec_env + '.c',
-)
+sources = files('log.c')
 headers = files('rte_log.h')
lib/log/version.map +0 -1
index 879567ba15..a0341196d4 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
 	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#356 lore raw

PATCH v25 10/15 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c         | 6 +++++-
 lib/log/log_private.h | 9 +++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_private.h
lib/log/log.c +5 -1
index 3fe86ddcd7..48543ee941 100644
@@ -18,6 +18,7 @@
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -33,11 +34,13 @@ static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = vfprintf,
 };
 
 struct rte_eal_opt_loglevel {
@@ -74,6 +77,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = vfprintf;
 	return 0;
 }
 
@@ -470,7 +474,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, format, ap);
 	fflush(f);
 	return ret;
 }
lib/log/log_private.h new file +9 -0
new file mode 100644
index 0000000000..67d2463b2f
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Note: same as vfprintf() */
+typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
+
+#endif /* LOG_PRIVATE_H */
Signature · 1 line
2.45.2
#357 lore raw

PATCH v25 11/15 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 +++
 doc/guides/prog_guide/log_lib.rst   |  26 +++
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |   7 +-
 lib/log/log_internal.h              |   9 ++
 lib/log/log_private.h               |  11 ++
 lib/log/log_timestamp.c             | 240 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   6 +-
 lib/log/version.map                 |   1 +
 13 files changed, 348 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index a5c0c67357..40dd288d5f 100644
@@ -1054,6 +1054,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1161,6 +1174,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +26 -0
index ff9d1b54a2..504eefe1d2 100644
@@ -59,6 +59,32 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +12 -2
index ea45c79d5c..ec3b5c3dfd 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1616,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1838,7 +1840,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1846,7 +1848,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2210,6 +2219,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 118c1f593b..06bccbd026 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index fab633976d..ceaa1f9487 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index c9648b7da7..0fda2abb97 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +6 -1
index 48543ee941..6ab856272c 100644
@@ -21,7 +21,7 @@
 #include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
 struct rte_log_dynamic_type {
@@ -509,6 +509,11 @@ eal_log_syslog(const char *mode __rte_unused)
 void
 eal_log_init(const char *id __rte_unused)
 {
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = vfprintf;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +11 -0
index 67d2463b2f..67cfe72fc6 100644
@@ -3,7 +3,18 @@
 #ifndef LOG_PRIVATE_H
 #define LOG_PRIVATE_H
 
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
 /* Note: same as vfprintf() */
 typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
 
+bool log_timestamp_enabled(void);
+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);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +240 -0

240 lines not on this page · raw message

lib/log/meson.build +5 -1
index 891f77a237..04235f6ee5 100644
@@ -2,5 +2,9 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files('log.c')
+sources = files(
+        'log.c',
+        'log_timestamp.c',
+)
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index a0341196d4..155f8b3bbe 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog;
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#358 lore raw

PATCH v25 12/15 log: add optional support of syslog

In reply to Stephen Hemminger

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.

---
 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                         | 17 ++++
 lib/log/log_syslog.c                          | 88 +++++++++++++++++++
 lib/log/meson.build                           |  4 +
 lib/log/version.map                           |  2 +-
 9 files changed, 150 insertions(+), 43 deletions(-)
 create mode 100644 lib/log/log_syslog.c
app/test/test_eal_flags.c +3 -2
index 40dd288d5f..06295030b2 100644
@@ -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};
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -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
doc/guides/prog_guide/log_lib.rst +17 -0
index 504eefe1d2..abaedc7212 100644
@@ -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
lib/eal/common/eal_common_options.c +4 -1
index ec3b5c3dfd..ac1aadbef4 100644
@@ -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"
lib/log/log.c +16 -12
index 6ab856272c..f748551bc0 100644
@@ -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;
lib/log/log_private.h +17 -0
index 67cfe72fc6..532a481340 100644
@@ -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 */
lib/log/log_syslog.c new file +88 -0

88 lines not on this page · raw message

lib/log/meson.build +4 -0
index 04235f6ee5..4ac232786e 100644
@@ -7,4 +7,8 @@ sources = files(
         'log_timestamp.c',
 )
 
+if not is_windows
+    sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -1
index 155f8b3bbe..8be6907840 100644
@@ -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;
 };
Signature · 1 line
2.45.2
#359 lore raw

PATCH v25 13/15 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  15 +++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   4 +-
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 200 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |  16 +++
 lib/log/meson.build                 |   4 +
 lib/log/version.map                 |   1 +
 9 files changed, 258 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_journal.c
doc/guides/prog_guide/log_lib.rst +14 -0
index abaedc7212..476dedb097 100644
@@ -100,6 +100,20 @@ option. There are three possible settings for this option:
 
 If ``--syslog`` option is not specified, then only console (stderr) will be used.
 
+Messages can be redirected to systemd journal which is an enhanced version of syslog with the ``--log-journal`` option.
+
+There are three possible settings for this option:
+
+*auto*
+    If stderr is redirected to journal by ``systemd`` service
+    then use journal socket to instead of stderr for log.
+    This is the default.
+
+*never*
+    Do not try to use journal.
+
+*always*
+    Always try to direct messages to journal socket.
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +15 -0
index ac1aadbef4..6184d27ad3 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
@@ -1617,6 +1618,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
@@ -1840,6 +1842,16 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+	case OPT_LOG_JOURNAL_NUM:
+		if (eal_log_journal(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_JOURNAL);
+			return -1;
+		}
+		break;
+#endif
+
 	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
@@ -2217,6 +2229,9 @@ eal_common_usage(void)
 	       "  --"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
+#ifdef RTE_EXEC_ENV_LINUX
+	       "  --"OPT_LOG_JOURNAL"[=<when>]  Enable use of systemd journal\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..c5a1c70288 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_JOURNAL       "log-journal"
+	OPT_LOG_JOURNAL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +3 -1
index f748551bc0..96fa651e81 100644
@@ -511,7 +511,9 @@ eal_log_init(const char *id)
 	is_terminal = isatty(STDERR_FILENO);
 #endif
 
-	if (log_syslog_enabled(is_terminal))
+	if (log_journal_enabled())
+		log_journal_open(id);
+	else 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;
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +200 -0

200 lines not on this page · raw message

lib/log/log_private.h +16 -0
index 532a481340..d8602681b2 100644
@@ -34,4 +34,20 @@ bool log_syslog_enabled(bool is_tty);
 void log_syslog_open(const char *id, bool is_terminal);
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+bool log_journal_enabled(void);
+void log_journal_open(const char *id);
+#else
+static inline bool
+log_journal_enabled(void)
+{
+	return false;
+}
+
+static inline void
+log_journal_open(const char *id __rte_unused)
+{
+}
+#endif /* !RTE_EXEC_ENV_LINUX */
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +4 -0
index 4ac232786e..86e4452b19 100644
@@ -11,4 +11,8 @@ if not is_windows
     sources += files('log_syslog.c')
 endif
 
+if is_linux
+    sources += files('log_journal.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 8be6907840..800d3943bc 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.45.2
#360 lore raw

PATCH v25 14/15 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

---
 app/test/test_eal_flags.c           |  24 +++++
 doc/guides/prog_guide/log_lib.rst   |  15 +++
 lib/eal/common/eal_common_options.c |  11 +++
 lib/eal/common/eal_options.h        |   6 +-
 lib/log/log.c                       |  19 ++--
 lib/log/log_color.c                 | 148 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 230 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index 06295030b2..6ee56ec97a 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +15 -0
index 476dedb097..647c3fc28a 100644
@@ -59,6 +59,21 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+he optional argument ``when`` can be ``auto``, ``never``, or ``always``.
+The default setting is ``auto`` which enables color when the output to
+``stderr`` is a terminal.
+If the ``when`` argument is omitted, it defaults to ``always``.
+
+For example to turn off all coloring::
+
+	/path/to/app --log-color=none
+
+
 Log timestamp
 ~~~~~~~~~~~~~
 
lib/eal/common/eal_common_options.c +11 -0
index 6184d27ad3..de19b1c258 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1869,6 +1871,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2238,6 +2248,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +4 -2
index c5a1c70288..c0686c2544 100644
@@ -33,10 +33,12 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
-#define OPT_LOG_LEVEL         "log-level"
-	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_JOURNAL       "log-journal"
 	OPT_LOG_JOURNAL_NUM,
+#define OPT_LOG_LEVEL         "log-level"
+	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +13 -6
index 96fa651e81..8b7b394f49 100644
@@ -511,14 +511,21 @@ eal_log_init(const char *id)
 	is_terminal = isatty(STDERR_FILENO);
 #endif
 
-	if (log_journal_enabled())
+	if (log_journal_enabled()) {
 		log_journal_open(id);
-	else if (log_syslog_enabled(is_terminal))
+	} else 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;
+	} else if (log_timestamp_enabled()) {
+		if (log_color_enabled(is_terminal))
+			rte_logs.print_func = color_print_with_timestamp;
+		else
+			rte_logs.print_func = log_print_with_timestamp;
+	} else {
+		if (log_color_enabled(is_terminal))
+			rte_logs.print_func = color_print;
+		else
+			rte_logs.print_func = vfprintf;
+	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
lib/log/log_color.c new file +148 -0

148 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index d8602681b2..855e32db90 100644
@@ -50,4 +50,12 @@ log_journal_open(const char *id __rte_unused)
 }
 #endif /* !RTE_EXEC_ENV_LINUX */
 
+bool log_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 86e4452b19..b3de57b9c7 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -0
index 800d3943bc..09d8a4289b 100644
@@ -25,6 +25,7 @@ DPDK_25 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
Signature · 1 line
2.45.2
#361 lore raw

PATCH v25 15/15 doc: add release note about log library

In reply to Stephen Hemminger

Significant enough to add some documentation.

---
 doc/guides/rel_notes/release_24_11.rst | 27 ++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
doc/guides/rel_notes/release_24_11.rst +27 -0
index 0ff70d9057..d6fb6c137b 100644
@@ -55,6 +55,33 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Enhancements to logging library.**
+
+  * Syslog related changes
+
+    * The meaning of the *--syslog* option has changed.
+      Use of syslog is controlled by the *--syslog* option.
+      The default is now *auto* which uses syslog only if stderr
+      is not a terminal device.
+
+    * The syslog facility is now set to **LOG_USER** if stderr is a terminal
+      and **LOG_DAEMON** otherwise.
+
+    * Syslog is now supported on FreeBSD (but not on Windows).
+
+  * The log is initialized earlier in startup so all messages go through
+    the library.
+
+  * Added a new option to timestamp log messages, which is useful for
+    debugging delays in application and driver startup.
+
+  * Log messages are now in color if going to a terminal (similar to dmesg).
+    The default format shows timestamp in green, subsystem in yellow,
+    and the message is bold, boldface or normal depending on severity.
+
+  * If the application is a systemd service and the log output is being
+    sent of standard error then DPDK will switch to journal native protocol.
+
 
 Removed Items
 -------------
Signature · 1 line
2.45.2
#364 lore raw

v26 cover Log subsystem improvements

In reply to Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

v26 - rebase and change release note
- by default, do not disable color
- support dark mode with colors
- when using color format message to string then print to avoid getting multiple threads intermixing on output.

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  64 ++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 --
 doc/guides/prog_guide/log_lib.rst             |  76 +++++-
 doc/guides/rel_notes/release_24_11.rst        |  26 ++
 lib/eal/common/eal_common_debug.c             |   6 +-
 lib/eal/common/eal_common_options.c           | 135 ++++++----
 lib/eal/common/eal_internal_cfg.h             |   1 -
 lib/eal/common/eal_options.h                  |   7 +
 lib/eal/freebsd/eal.c                         |  64 +----
 lib/eal/linux/eal.c                           |  68 +----
 lib/eal/windows/eal.c                         |  49 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  71 ++++--
 lib/log/log_color.c                           | 216 ++++++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 +-
 lib/log/log_journal.c                         | 200 +++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  61 +++++
 lib/log/log_syslog.c                          |  88 +++++++
 lib/log/log_timestamp.c                       | 240 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  12 +-
 lib/log/version.map                           |   5 +-
 27 files changed, 1197 insertions(+), 380 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.45.2
#365 lore raw

PATCH v26 1/15 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index 6814991735..7141f490b2 100644
@@ -186,6 +186,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.45.2
#366 lore raw

PATCH v26 2/15 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.45.2
#367 lore raw

PATCH v26 3/15 windows: add os shim for localtime_r

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 1 file changed, 10 insertions(+)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..665c9ac93b 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timep, struct tm *result)
+{
+	if (localtime_s(result, timep) == 0)
+		return result;
+	else
+		return NULL;
+}
+#define localtime_r(timep, result) rte_localtime_r(timep, result)
+
 #endif /* _RTE_OS_SHIM_ */
Signature · 1 line
2.45.2
#368 lore raw

PATCH v26 4/15 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 40 +++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 -----------------------------
 lib/eal/linux/eal.c                 | 39 ---------------------------
 lib/eal/windows/eal.c               | 35 ------------------------
 5 files changed, 41 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +40 -0
index f1a5e329a5..eb079a65a9 100644
@@ -1640,6 +1640,46 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		}
+	}
+
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index 54577b7718..40d750ed0d 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 28b78a95a6..a77e590a72 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.45.2
#369 lore raw

PATCH v26 5/15 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index 40d750ed0d..c53a051405 100644
@@ -830,8 +830,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
Signature · 1 line
2.45.2
#370 lore raw

Re: [PATCH v26 05/15] eal: do not duplicate rte_init_alert() messages

Hello,

Quoted 34 lines · Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-       fprintf(stderr, "EAL: FATAL: %s\n", msg);
-       EAL_LOG(ERR, "%s", msg);
+       EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +0 -0
index 40d750ed0d..c53a051405 100644

lib/eal/linux/eal.c rte_eal_iopl_init(void) · line 836

Quoted 9 lines
lib/eal/linux/eal.c +1 -2
@@ -830,8 +830,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-       fprintf(stderr, "EAL: FATAL: %s\n", msg);
-       EAL_LOG(ERR, "%s", msg);
+       EAL_LOG(ALERT, "%s", msg);
 }
 
 /*

Any reason why Windows was not changed?

I can add the missing bit when applying.

Signature · 1 line
David Marchand
#371 lore raw

Re: [PATCH v26 05/15] eal: do not duplicate rte_init_alert() messages

Quoted 13 lines · On Thu, 17 Oct 2024 18:47:54 +0200 David Marchand <[email protected]>…
Quoted 13 lines
lib/eal/linux/eal.c +1 -2
index 40d750ed0d..c53a051405 100644
@@ -830,8 +830,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-       fprintf(stderr, "EAL: FATAL: %s\n", msg);
-       EAL_LOG(ERR, "%s", msg);
+       EAL_LOG(ALERT, "%s", msg);
 }
 
Quoted 5 lines

lib/eal/linux/eal.c rte_eal_iopl_init(void) · line 836

Quoted 1 line
lib/eal/linux/eal.c +0 -0
 /*  

Any reason why Windows was not changed?

I can add the missing bit when applying.

No reason that Windows was not changed, just forgot about it.

#372 lore raw

PATCH v26 6/15 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
lib/eal/common/eal_common_debug.c +2 -4
index 3e77995896..bcfcd6df6f 100644
@@ -36,15 +36,13 @@ rte_exit(int exit_code, const char *format, ...)
 	va_list ap;
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
 	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
 	va_end(ap);
 
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.45.2
#373 lore raw

PATCH v26 7/15 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also allows for changes to what syslog flag means in later steps.

---
 lib/eal/common/eal_common_options.c | 51 ++---------------------------
 lib/eal/common/eal_internal_cfg.h   |  1 -
 lib/eal/freebsd/eal.c               |  5 ++-
 lib/eal/linux/eal.c                 |  7 ++--
 lib/eal/windows/eal.c               |  6 ++--
 lib/log/log.c                       |  2 ++
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 ++-
 lib/log/log_linux.c                 | 47 ++++++++++++++++++++++++--
 lib/log/log_windows.c               |  8 ++++-
 lib/log/version.map                 |  1 +
 11 files changed, 70 insertions(+), 65 deletions(-)
lib/eal/common/eal_common_options.c +2 -49
index eb079a65a9..918cc013fe 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -349,10 +346,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1290,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1615,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1877,7 +1830,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/common/eal_internal_cfg.h +0 -1
index 167ec501fa..f53ab8b4aa 100644
@@ -84,7 +84,6 @@ struct internal_config {
 	/**< true if storing all pages within single files (per-page-size,
 	 * per-node) non-legacy mode only.
 	 */
-	volatile int syslog_facility;	  /**< facility passed to openlog() */
 	/** default interrupt mode for VFIO */
 	volatile enum rte_intr_mode vfio_intr_mode;
 	/** the shared VF token for VFIO-PCI bound PF and VFs devices */
lib/eal/freebsd/eal.c +2 -3
index 7b974608e4..a609d40ee0 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index c53a051405..9a0a1cf211 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1103,8 +1103,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index a77e590a72..69a8fc8d80 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -250,7 +250,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 255f757d94..4b24e145b6 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c +45 -2

72 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/version.map +1 -0
index 19d7f9cdb6..879567ba15 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#374 lore raw

PATCH v26 8/15 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_linux.c    | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index a609d40ee0..118c1f593b 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -572,9 +581,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 9a0a1cf211..62d3d281c4 100644
@@ -926,6 +926,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -949,9 +958,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1103,13 +1109,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_vfio_enable("vfio")) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index 69a8fc8d80..c9648b7da7 100644
@@ -250,9 +250,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_linux.c +6 -8
index 47aa074da2..6d7dc8f3ab 100644
@@ -87,18 +87,16 @@ static cookie_io_functions_t console_log_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", console_log_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", console_log_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.45.2
#375 lore raw

PATCH v26 9/15 log: drop syslog support, and make code common

In reply to Stephen Hemminger

This patch makes the log setup code common across all platforms.

Drops syslog support for now, will come back in later patch.

---
 app/test/test_eal_flags.c           |  11 ++-
 lib/eal/common/eal_common_options.c |   3 -
 lib/log/log.c                       |  41 +++++------
 lib/log/log_freebsd.c               |  11 ---
 lib/log/log_internal.h              |   6 --
 lib/log/log_linux.c                 | 102 ----------------------------
 lib/log/log_windows.c               |  22 ------
 lib/log/meson.build                 |   5 +-
 lib/log/version.map                 |   1 -
 9 files changed, 23 insertions(+), 179 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +5 -6
index 71d8dba731..a5c0c67357 100644
@@ -984,11 +984,10 @@ test_misc_flags(void)
 	const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+	/* With empty --syslog */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
-	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog", "always"};
 	/* With invalid --syslog */
 	const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
 	/* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
@@ -1083,8 +1082,8 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not with --syslog always flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
lib/eal/common/eal_common_options.c +0 -3
index 918cc013fe..ea45c79d5c 100644
@@ -2206,9 +2206,6 @@ 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"            Set syslog facility\n"
-#endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
lib/log/log.c +17 -24

73 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_linux.c deleted +0 -102

102 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/meson.build +1 -4
index 0d4319b36f..891f77a237 100644
@@ -2,8 +2,5 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files(
-        'log.c',
-        'log_' + exec_env + '.c',
-)
+sources = files('log.c')
 headers = files('rte_log.h')
lib/log/version.map +0 -1
index 879567ba15..a0341196d4 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
 	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#376 lore raw

PATCH v26 10/15 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c         | 6 +++++-
 lib/log/log_private.h | 9 +++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_private.h
lib/log/log.c +5 -1
index 3fe86ddcd7..48543ee941 100644
@@ -18,6 +18,7 @@
 #include <rte_per_lcore.h>
 
 #include "log_internal.h"
+#include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #define strdup _strdup
@@ -33,11 +34,13 @@ static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = vfprintf,
 };
 
 struct rte_eal_opt_loglevel {
@@ -74,6 +77,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = vfprintf;
 	return 0;
 }
 
@@ -470,7 +474,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, format, ap);
 	fflush(f);
 	return ret;
 }
lib/log/log_private.h new file +9 -0
new file mode 100644
index 0000000000..67d2463b2f
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Note: same as vfprintf() */
+typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
+
+#endif /* LOG_PRIVATE_H */
Signature · 1 line
2.45.2
#377 lore raw

PATCH v26 11/15 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 +++
 doc/guides/prog_guide/log_lib.rst   |  26 +++
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |   7 +-
 lib/log/log_internal.h              |   9 ++
 lib/log/log_private.h               |  11 ++
 lib/log/log_timestamp.c             | 240 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   6 +-
 lib/log/version.map                 |   1 +
 13 files changed, 348 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index a5c0c67357..40dd288d5f 100644
@@ -1054,6 +1054,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1161,6 +1174,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +26 -0
index ff9d1b54a2..504eefe1d2 100644
@@ -59,6 +59,32 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +12 -2
index ea45c79d5c..ec3b5c3dfd 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1616,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1838,7 +1840,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1846,7 +1848,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2210,6 +2219,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 118c1f593b..06bccbd026 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index 62d3d281c4..cf2f0fcab9 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index c9648b7da7..0fda2abb97 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +6 -1
index 48543ee941..6ab856272c 100644
@@ -21,7 +21,7 @@
 #include "log_private.h"
 
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
 struct rte_log_dynamic_type {
@@ -509,6 +509,11 @@ eal_log_syslog(const char *mode __rte_unused)
 void
 eal_log_init(const char *id __rte_unused)
 {
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = vfprintf;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +11 -0
index 67d2463b2f..67cfe72fc6 100644
@@ -3,7 +3,18 @@
 #ifndef LOG_PRIVATE_H
 #define LOG_PRIVATE_H
 
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
 /* Note: same as vfprintf() */
 typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
 
+bool log_timestamp_enabled(void);
+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);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +240 -0

240 lines not on this page · raw message

lib/log/meson.build +5 -1
index 891f77a237..04235f6ee5 100644
@@ -2,5 +2,9 @@
 # Copyright(c) 2023 Intel Corporation
 
 includes += global_inc
-sources = files('log.c')
+sources = files(
+        'log.c',
+        'log_timestamp.c',
+)
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index a0341196d4..155f8b3bbe 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog;
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#378 lore raw

PATCH v26 12/15 log: add optional support of syslog

In reply to Stephen Hemminger

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.

---
 app/test/test_eal_flags.c                     |  5 +-
 doc/guides/linux_gsg/linux_eal_parameters.rst | 27 ------
 doc/guides/prog_guide/log_lib.rst             | 21 ++++-
 lib/eal/common/eal_common_options.c           |  5 +-
 lib/log/log.c                                 | 28 +++---
 lib/log/log_private.h                         | 17 ++++
 lib/log/log_syslog.c                          | 88 +++++++++++++++++++
 lib/log/meson.build                           |  4 +
 lib/log/version.map                           |  2 +-
 9 files changed, 151 insertions(+), 46 deletions(-)
 create mode 100644 lib/log/log_syslog.c
app/test/test_eal_flags.c +3 -2
index 40dd288d5f..06295030b2 100644
@@ -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};
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -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
doc/guides/prog_guide/log_lib.rst +18 -3
index 504eefe1d2..6ae40f6a3a 100644
@@ -5,9 +5,7 @@ Log Library
 ===========
 
 The DPDK Log library provides the logging functionality for other DPDK libraries and drivers.
-By default, in a Linux application, logs are sent to syslog and also to the console.
-On FreeBSD and Windows applications, logs are sent only to the console.
-However, the log function can be overridden by the user to use a different logging mechanism.
+The messages can be sent to one or more sources controlled by the EAL command line options.
 
 Log Levels
 ----------
@@ -83,6 +81,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
lib/eal/common/eal_common_options.c +4 -1
index ec3b5c3dfd..ac1aadbef4 100644
@@ -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"
lib/log/log.c +16 -12
index 6ab856272c..f748551bc0 100644
@@ -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;
lib/log/log_private.h +17 -0
index 67cfe72fc6..532a481340 100644
@@ -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 */
lib/log/log_syslog.c new file +88 -0

88 lines not on this page · raw message

lib/log/meson.build +4 -0
index 04235f6ee5..4ac232786e 100644
@@ -7,4 +7,8 @@ sources = files(
         'log_timestamp.c',
 )
 
+if not is_windows
+    sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -1
index 155f8b3bbe..8be6907840 100644
@@ -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;
 };
Signature · 1 line
2.45.2
#379 lore raw

PATCH v26 13/15 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 doc/guides/prog_guide/log_lib.rst   |  14 ++
 lib/eal/common/eal_common_options.c |  15 +++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |   4 +-
 lib/log/log_internal.h              |   3 +
 lib/log/log_journal.c               | 200 ++++++++++++++++++++++++++++
 lib/log/log_private.h               |  16 +++
 lib/log/meson.build                 |   4 +
 lib/log/version.map                 |   1 +
 9 files changed, 258 insertions(+), 1 deletion(-)
 create mode 100644 lib/log/log_journal.c
doc/guides/prog_guide/log_lib.rst +14 -0
index 6ae40f6a3a..925bc70ede 100644
@@ -98,6 +98,20 @@ option. There are three possible settings for this option:
 
 If ``--syslog`` option is not specified, then only console (stderr) will be used.
 
+Messages can be redirected to systemd journal which is an enhanced version of syslog with the ``--log-journal`` option.
+
+There are three possible settings for this option:
+
+*auto*
+    If stderr is redirected to journal by ``systemd`` service
+    then use journal socket to instead of stderr for log.
+    This is the default.
+
+*never*
+    Do not try to use journal.
+
+*always*
+    Always try to direct messages to journal socket.
 
 
 Using Logging APIs to Generate Log Messages
lib/eal/common/eal_common_options.c +15 -0
index ac1aadbef4..6184d27ad3 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
@@ -1617,6 +1618,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
@@ -1840,6 +1842,16 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+	case OPT_LOG_JOURNAL_NUM:
+		if (eal_log_journal(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_JOURNAL);
+			return -1;
+		}
+		break;
+#endif
+
 	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
@@ -2217,6 +2229,9 @@ eal_common_usage(void)
 	       "  --"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
+#ifdef RTE_EXEC_ENV_LINUX
+	       "  --"OPT_LOG_JOURNAL"[=<when>]  Enable use of systemd journal\n"
 #endif
 	       "  --"OPT_LOG_LEVEL"=<level> Set global log level\n"
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..c5a1c70288 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_JOURNAL       "log-journal"
+	OPT_LOG_JOURNAL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +3 -1
index f748551bc0..96fa651e81 100644
@@ -511,7 +511,9 @@ eal_log_init(const char *id)
 	is_terminal = isatty(STDERR_FILENO);
 #endif
 
-	if (log_syslog_enabled(is_terminal))
+	if (log_journal_enabled())
+		log_journal_open(id);
+	else 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;
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +200 -0

200 lines not on this page · raw message

lib/log/log_private.h +16 -0
index 532a481340..d8602681b2 100644
@@ -34,4 +34,20 @@ bool log_syslog_enabled(bool is_tty);
 void log_syslog_open(const char *id, bool is_terminal);
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+bool log_journal_enabled(void);
+void log_journal_open(const char *id);
+#else
+static inline bool
+log_journal_enabled(void)
+{
+	return false;
+}
+
+static inline void
+log_journal_open(const char *id __rte_unused)
+{
+}
+#endif /* !RTE_EXEC_ENV_LINUX */
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +4 -0
index 4ac232786e..86e4452b19 100644
@@ -11,4 +11,8 @@ if not is_windows
     sources += files('log_syslog.c')
 endif
 
+if is_linux
+    sources += files('log_journal.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 8be6907840..800d3943bc 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.45.2
#380 lore raw

PATCH v26 14/15 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

The default is to not use color since it may disturb automatic tests and other embedded usage.

log dark

---
 app/test/test_eal_flags.c           |  24 ++++
 doc/guides/prog_guide/log_lib.rst   |  15 ++
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   6 +-
 lib/log/log.c                       |  19 ++-
 lib/log/log_color.c                 | 216 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 298 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index 06295030b2..6ee56ec97a 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +15 -0
index 925bc70ede..b533e2d48e 100644
@@ -57,6 +57,21 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+he optional argument ``when`` can be ``auto``, ``never``, or ``always``.
+The default setting is ``auto`` which enables color when the output to
+``stderr`` is a terminal.
+If the ``when`` argument is omitted, it defaults to ``always``.
+
+For example to turn off all coloring::
+
+	/path/to/app --log-color=none
+
+
 Log timestamp
 ~~~~~~~~~~~~~
 
lib/eal/common/eal_common_options.c +11 -0
index 6184d27ad3..de19b1c258 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_JOURNAL,	2, NULL, OPT_LOG_JOURNAL_NUM	  },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_JOURNAL_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1869,6 +1871,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2238,6 +2248,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +4 -2
index c5a1c70288..c0686c2544 100644
@@ -33,10 +33,12 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
-#define OPT_LOG_LEVEL         "log-level"
-	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_JOURNAL       "log-journal"
 	OPT_LOG_JOURNAL_NUM,
+#define OPT_LOG_LEVEL         "log-level"
+	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
 	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
lib/log/log.c +13 -6
index 96fa651e81..8b7b394f49 100644
@@ -511,14 +511,21 @@ eal_log_init(const char *id)
 	is_terminal = isatty(STDERR_FILENO);
 #endif
 
-	if (log_journal_enabled())
+	if (log_journal_enabled()) {
 		log_journal_open(id);
-	else if (log_syslog_enabled(is_terminal))
+	} else 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;
+	} else if (log_timestamp_enabled()) {
+		if (log_color_enabled(is_terminal))
+			rte_logs.print_func = color_print_with_timestamp;
+		else
+			rte_logs.print_func = log_print_with_timestamp;
+	} else {
+		if (log_color_enabled(is_terminal))
+			rte_logs.print_func = color_print;
+		else
+			rte_logs.print_func = vfprintf;
+	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
lib/log/log_color.c new file +216 -0

216 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index d8602681b2..855e32db90 100644
@@ -50,4 +50,12 @@ log_journal_open(const char *id __rte_unused)
 }
 #endif /* !RTE_EXEC_ENV_LINUX */
 
+bool log_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 86e4452b19..b3de57b9c7 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -0
index 800d3943bc..09d8a4289b 100644
@@ -25,6 +25,7 @@ DPDK_25 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
Signature · 1 line
2.45.2
#381 lore raw

PATCH v26 15/15 doc: add release note about log library

In reply to Stephen Hemminger

Significant enough to add some documentation.

---
 doc/guides/rel_notes/release_24_11.rst | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
doc/guides/rel_notes/release_24_11.rst +26 -0
index acc512c70a..5c8a0af1d0 100644
@@ -276,6 +276,32 @@ API Changes
   and replaced it with a new shared devarg ``llq_policy`` that keeps the same logic.
 
 
+* **Logging library changes**
+
+  * The log is initialized earlier in startup so all messages go through
+    the library.
+
+  * Added a new option to timestamp log messages, which is useful for
+    debugging delays in application and driver startup.
+
+  * Syslog related changes
+
+    * The meaning of the *--syslog* option has changed.
+      Use of syslog is controlled by the *--syslog* option.
+      The default is now *auto* which uses syslog only if stderr
+      is not a terminal device.
+
+    * The syslog facility is now set to **LOG_USER** if stderr is a terminal
+      and **LOG_DAEMON** otherwise.
+
+    * Syslog is now supported on FreeBSD (but not on Windows).
+
+  * If the application is a systemd service and the log output is being
+    sent of standard error then DPDK will switch to journal native protocol.
+
+  * Log messages can be optionally marked with colors.
+
+
 ABI Changes
 -----------
 
Signature · 1 line
2.45.2
#382 lore raw

Re: [PATCH v26 00/15] Log subsystem improvements

In reply to Stephen Hemminger

Hello Stephen,

Quoted 29 lines · Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

Quoted 6 lines

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

Thanks for the series.

Overall, it looks good, but I am too short on time for merging in rc1 and I have some comments.
I'll consider merging it in rc2.

- The main point is the "automatic" aspect but we want to provide some way to force where the logs end up.
With this series, the user has --syslog (whose meaning is changed) and --log-journal options to affect where the logs go.
Can we get a single option?
Like maybe --log-destination=console|syslog|journal|auto ?

- I don't really understand why changing the --syslog is better. We lose the ability to select the syslog facility. Either this feature was useless, and I would rather deprecate or remove it explicitly (and the --syslog with it).
Or we should keep it as is for compat reason.

- The color and timestamping options only affect the console output, which is not clear with the --log-color / --log-timestamp names. Maybe we can enhance with some other name?

- Did you test redirecting all logs to an external logging function? I suppose it still works, but it is important not to break such feature for OVS.

Signature · 1 line
David Marchand
#383 lore raw

Re: [PATCH v26 00/15] Log subsystem improvements

Quoted 47 lines · On Fri, 18 Oct 2024 19:07:18 +0200 David Marchand <[email protected]>…

Hello Stephen,

Quoted 29 lines · Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

Quoted 6 lines

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

Thanks for the series.

Overall, it looks good, but I am too short on time for merging in rc1 and I have some comments.
I'll consider merging it in rc2.

Quoted 6 lines

- The main point is the "automatic" aspect but we want to provide some way to force where the logs end up.
With this series, the user has --syslog (whose meaning is changed) and --log-journal options to affect where the logs go.
Can we get a single option?
Like maybe --log-destination=console|syslog|journal|auto ?

That could work. The goal here is to do the right thing without options. And reduce the duplication. Right now, applications end up logging to both console and syslog.

Quoted 6 lines

- I don't really understand why changing the --syslog is better. We lose the ability to select the syslog facility. Either this feature was useless, and I would rather deprecate or remove it explicitly (and the --syslog with it).
Or we should keep it as is for compat reason.

Syslog facility really was pretty useless. The number of facilities is too small and there never was a good reason to have it.

Maybe keep old option syntax as fallback?

Quoted 4 lines

- The color and timestamping options only affect the console output, which is not clear with the --log-color / --log-timestamp names. Maybe we can enhance with some other name?

Timestamp is unneeded with syslog or journal since they do it already. It is possible to force timestamp or color when going to a file (by setting log stream).

Did consider that options could be: --color and --timestamp but seemed better to keep all log related options together.

Quoted 3 lines

- Did you test redirecting all logs to an external logging function? I suppose it still works, but it is important not to break such feature for OVS.

Did not have test for that, should be put in functional tests.

I flip/flopped on default for color. I like the auto mode and it might make users see errors more. But concerned that things like CI which are capturing via pseudo-terminals might get color and not know what to do with it. Final version defaults to off.

#384 lore raw

Re: [PATCH v26 00/15] Log subsystem improvements

In reply to Stephen Hemminger

Hi,

I'm not sure about the proper way to do a code review here, feel free to educate me if there is a better way to do it. I couldn't find the actual patches text in the mail and patchwork has no interface to write comments on the line itself but I may very well have missed something.

https://patches.dpdk.org/project/dpdk/patch/[email protected]/
Why not provide an option to disable the syslog with --syslog=none? It will allow overriding a previous setting if one was given as well.

(the same applies to the --log-journal option)

https://patches.dpdk.org/project/dpdk/patch/[email protected]/
You have both --log-color=never and --log-color=none, you probably need to make up your mind, my vote would be with none for better compatibility with the syslog/journal options I made above. But I don't care that much about it.

Would also be good to document about the dark mode option so people don't need to find it only in the code.

Baruch

Quoted 99 lines · Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use syslog if output is going to a terminal.

Add myself as maintainer for log because by now have added more than previous authors.

v26 - rebase and change release note
- by default, do not disable color
- support dark mode with colors
- when using color format message to string then print to avoid getting multiple threads intermixing on output.

Stephen Hemminger (15):
maintainers: add for log library
windows: make getopt functions have const properties
windows: add os shim for localtime_r
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: drop syslog support, and make code common
log: add hook for printing log messages
log: add timestamp option
log: add optional support of syslog
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  64 ++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 --
 doc/guides/prog_guide/log_lib.rst             |  76 +++++-
 doc/guides/rel_notes/release_24_11.rst        |  26 ++
 lib/eal/common/eal_common_debug.c             |   6 +-
 lib/eal/common/eal_common_options.c           | 135 ++++++----
 lib/eal/common/eal_internal_cfg.h             |   1 -
 lib/eal/common/eal_options.h                  |   7 +
 lib/eal/freebsd/eal.c                         |  64 +----
 lib/eal/linux/eal.c                           |  68 +----
 lib/eal/windows/eal.c                         |  49 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  71 ++++--
 lib/log/log_color.c                           | 216 ++++++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 +-
 lib/log/log_journal.c                         | 200 +++++++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  61 +++++
 lib/log/log_syslog.c                          |  88 +++++++
 lib/log/log_timestamp.c                       | 240 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  12 +-
 lib/log/version.map                           |   5 +-
 27 files changed, 1197 insertions(+), 380 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c

--
2.45.2

Signature · 6 lines
Baruch Even
Platform Technical Lead at WEKA
E [email protected]* ­*W https://www.weka.io* ­*

[image: App Banner Image]
<https://www.weka.io/trends-in-AI-emsig?utm_campaign=signature&utm_source=WiseStamp&utm_medium=email>
#385 lore raw

v27 cover Log subsystem changes

In reply to Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use unless requested.

Add myself as maintainer for log because by now have added more than previous authors.

v27 - review feedback
- consolidate and simplify
- keep the meaning of --syslog=facility the same as before.

v26 - rebase and change release note
- by default, do not disable color
- support dark mode with colors
- when using color format message to string then print to avoid getting multiple threads intermixing on output.

Stephen Hemminger (14):
maintainers: add for log library
windows: make getopt functions have const properties
windows: update os shim
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: move handling of syslog facility out of eal
eal: initialize log before everything else
log: add hook for printing log messages
log: modify syslog handling
log: add timestamp option
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  66 ++++-
 doc/guides/linux_gsg/linux_eal_parameters.rst |  27 --
 doc/guides/prog_guide/log_lib.rst             |  57 +++-
 doc/guides/rel_notes/release_24_11.rst        |  19 ++
 lib/eal/common/eal_common_debug.c             |   6 +-
 lib/eal/common/eal_common_options.c           | 122 +++++----
 lib/eal/common/eal_internal_cfg.h             |   1 -
 lib/eal/common/eal_options.h                  |   5 +
 lib/eal/freebsd/eal.c                         |  64 +----
 lib/eal/linux/eal.c                           |  68 +----
 lib/eal/windows/eal.c                         |  50 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  76 ++++--
 lib/log/log_color.c                           | 216 +++++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  28 +-
 lib/log/log_journal.c                         | 154 +++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  36 +++
 lib/log/log_syslog.c                          | 106 ++++++++
 lib/log/log_timestamp.c                       | 245 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  12 +-
 lib/log/version.map                           |   5 +-
 27 files changed, 1114 insertions(+), 382 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.45.2
#386 lore raw

PATCH v27 1/14 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index cd78bc7db1..a504b8fc54 100644
@@ -186,6 +186,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.45.2
#387 lore raw

PATCH v27 2/14 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.45.2
#388 lore raw

PATCH v27 3/14 windows: update os shim

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

Use rte_os_shim.h in lib/log instead of redefine of strdup.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 lib/log/log.c                         |  7 +++----
 2 files changed, 13 insertions(+), 4 deletions(-)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..665c9ac93b 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timep, struct tm *result)
+{
+	if (localtime_s(result, timep) == 0)
+		return result;
+	else
+		return NULL;
+}
+#define localtime_r(timep, result) rte_localtime_r(timep, result)
+
 #endif /* _RTE_OS_SHIM_ */
lib/log/log.c +3 -4
index 255f757d94..7416c82b34 100644
@@ -14,13 +14,12 @@
 
 #include <rte_log.h>
 #include <rte_per_lcore.h>
-
-#include "log_internal.h"
-
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
+#include "log_internal.h"
+
 struct rte_log_dynamic_type {
 	const char *name;
 	uint32_t loglevel;
Signature · 1 line
2.45.2
#389 lore raw

PATCH v27 4/14 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 40 +++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 -----------------------------
 lib/eal/linux/eal.c                 | 39 ---------------------------
 lib/eal/windows/eal.c               | 35 ------------------------
 5 files changed, 41 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +40 -0
index f1a5e329a5..eb079a65a9 100644
@@ -1640,6 +1640,46 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		}
+	}
+
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index 54577b7718..40d750ed0d 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 28b78a95a6..a77e590a72 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.45.2
#390 lore raw

PATCH v27 5/14 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 lib/eal/windows/eal.c | 1 -
 3 files changed, 2 insertions(+), 5 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index 40d750ed0d..c53a051405 100644
@@ -830,8 +830,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
lib/eal/windows/eal.c +0 -1
index a77e590a72..93f099a968 100644
@@ -181,7 +181,6 @@ sync_func(void *arg __rte_unused)
 static void
 rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
 	EAL_LOG(ERR, "%s", msg);
 }
 
Signature · 1 line
2.45.2
#391 lore raw

PATCH v27 6/14 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
lib/eal/common/eal_common_debug.c +2 -4
index 3e77995896..bcfcd6df6f 100644
@@ -36,15 +36,13 @@ rte_exit(int exit_code, const char *format, ...)
 	va_list ap;
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
 	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
 	va_end(ap);
 
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.45.2
#392 lore raw

PATCH v27 7/14 log: move handling of syslog facility out of eal

In reply to Stephen Hemminger

The syslog facility property is better handled in lib/log rather than in eal. This also add syslog support to FreeBSD.

---
 lib/eal/common/eal_common_options.c | 53 ++--------------
 lib/eal/common/eal_internal_cfg.h   |  1 -
 lib/eal/freebsd/eal.c               |  5 +-
 lib/eal/linux/eal.c                 |  7 +--
 lib/eal/windows/eal.c               |  6 +-
 lib/log/log.c                       |  2 +
 lib/log/log_freebsd.c               |  2 +-
 lib/log/log_internal.h              |  5 +-
 lib/log/log_linux.c                 | 61 ------------------
 lib/log/log_syslog.c                | 98 +++++++++++++++++++++++++++++
 lib/log/log_windows.c               |  8 ++-
 lib/log/meson.build                 |  6 +-
 lib/log/version.map                 |  1 +
 13 files changed, 130 insertions(+), 125 deletions(-)
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_syslog.c
lib/eal/common/eal_common_options.c +4 -49
index eb079a65a9..71c672e93e 100644
@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-#ifndef RTE_EXEC_ENV_WINDOWS
-#include <syslog.h>
-#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
@@ -93,7 +90,9 @@ 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     },
+#ifndef RTE_EXEC_ENV_WINDOWS
 	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
+#endif
 	{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    },
@@ -349,10 +348,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
 	}
 	internal_cfg->base_virtaddr = 0;
 
-#ifdef LOG_DAEMON
-	internal_cfg->syslog_facility = LOG_DAEMON;
-#endif
-
 	/* if set to NONE, interrupt mode is determined automatically */
 	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
 	memset(internal_cfg->vfio_vf_token, 0,
@@ -1297,47 +1292,6 @@ eal_parse_lcores(const char *lcores)
 	return ret;
 }
 
-#ifndef RTE_EXEC_ENV_WINDOWS
-static int
-eal_parse_syslog(const char *facility, struct internal_config *conf)
-{
-	int i;
-	static const struct {
-		const char *name;
-		int value;
-	} map[] = {
-		{ "auth", LOG_AUTH },
-		{ "cron", LOG_CRON },
-		{ "daemon", LOG_DAEMON },
-		{ "ftp", LOG_FTP },
-		{ "kern", LOG_KERN },
-		{ "lpr", LOG_LPR },
-		{ "mail", LOG_MAIL },
-		{ "news", LOG_NEWS },
-		{ "syslog", LOG_SYSLOG },
-		{ "user", LOG_USER },
-		{ "uucp", LOG_UUCP },
-		{ "local0", LOG_LOCAL0 },
-		{ "local1", LOG_LOCAL1 },
-		{ "local2", LOG_LOCAL2 },
-		{ "local3", LOG_LOCAL3 },
-		{ "local4", LOG_LOCAL4 },
-		{ "local5", LOG_LOCAL5 },
-		{ "local6", LOG_LOCAL6 },
-		{ "local7", LOG_LOCAL7 },
-		{ NULL, 0 }
-	};
-
-	for (i = 0; map[i].name; i++) {
-		if (!strcmp(facility, map[i].name)) {
-			conf->syslog_facility = map[i].value;
-			return 0;
-		}
-	}
-	return -1;
-}
-#endif
-
 static void
 eal_log_usage(void)
 {
@@ -1663,6 +1617,7 @@ eal_log_level_parse(int argc, char * const argv[])
 
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
+		case OPT_SYSLOG_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1877,7 +1832,7 @@ eal_parse_common_option(int opt, const char *optarg,
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_SYSLOG_NUM:
-		if (eal_parse_syslog(optarg, conf) < 0) {
+		if (eal_log_syslog(optarg) < 0) {
 			EAL_LOG(ERR, "invalid parameters for --"
 					OPT_SYSLOG);
 			return -1;
lib/eal/common/eal_internal_cfg.h +0 -1
index 167ec501fa..f53ab8b4aa 100644
@@ -84,7 +84,6 @@ struct internal_config {
 	/**< true if storing all pages within single files (per-page-size,
 	 * per-node) non-legacy mode only.
 	 */
-	volatile int syslog_facility;	  /**< facility passed to openlog() */
 	/** default interrupt mode for VFIO */
 	volatile enum rte_intr_mode vfio_intr_mode;
 	/** the shared VF token for VFIO-PCI bound PF and VFs devices */
lib/eal/freebsd/eal.c +2 -3
index 7b974608e4..a609d40ee0 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -4
index c53a051405..9a0a1cf211 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1103,8 +1103,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
+	if (eal_log_init(program_invocation_short_name) < 0) {
 		rte_eal_init_alert("Cannot init logging.");
 		rte_errno = ENOMEM;
 		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
lib/eal/windows/eal.c +3 -3
index 93f099a968..cd8420a82c 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -249,7 +249,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +2 -0
index 7416c82b34..d41ca2ed31 100644
@@ -2,6 +2,7 @@
  * Copyright(c) 2010-2014 Intel Corporation
  */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdarg.h>
@@ -12,6 +13,7 @@
 #include <fnmatch.h>
 #include <sys/queue.h>
 
+#include <rte_common.h>
 #include <rte_log.h>
 #include <rte_per_lcore.h>
 #ifdef RTE_EXEC_ENV_WINDOWS
lib/log/log_freebsd.c +1 -1
index 698d3c5423..953e371bee 100644
@@ -6,7 +6,7 @@
 #include "log_internal.h"
 
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	return 0;
 }
lib/log/log_internal.h +4 -1
index 451629f1c1..cb15cdff08 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
+int eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
@@ -30,6 +30,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c deleted +0 -61

61 lines not on this page · raw message

lib/log/log_syslog.c new file +98 -0

98 lines not on this page · raw message

lib/log/log_windows.c +7 -1
index a6a0889550..a3a756351d 100644
@@ -6,9 +6,15 @@
 #include <rte_log.h>
 #include "log_internal.h"
 
+int
+eal_log_syslog(const char *name __rte_unused)
+{
+	return -1; /* not used */
+}
+
 /* set the log to default function, called during eal init process. */
 int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
+eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
lib/log/meson.build +5 -1
index 0d4319b36f..160cf34f50 100644
@@ -4,6 +4,10 @@
 includes += global_inc
 sources = files(
         'log.c',
-        'log_' + exec_env + '.c',
 )
+
+if not is_windows
+    sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 19d7f9cdb6..879567ba15 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_set_default;
+	eal_log_syslog;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#393 lore raw

PATCH v27 8/14 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 12 +++++++++---
 lib/eal/linux/eal.c    | 19 +++++++++----------
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_freebsd.c  |  3 +--
 lib/log/log_internal.h |  2 +-
 lib/log/log_syslog.c   | 14 ++++++--------
 lib/log/log_windows.c  |  4 +---
 7 files changed, 33 insertions(+), 29 deletions(-)
lib/eal/freebsd/eal.c +9 -3
index a609d40ee0..118c1f593b 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,14 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -572,9 +581,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -10
index 9a0a1cf211..62d3d281c4 100644
@@ -926,6 +926,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -949,9 +958,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1103,13 +1109,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
-
 #ifdef VFIO_PRESENT
 	if (rte_vfio_enable("vfio")) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index cd8420a82c..33f044d7cc 100644
@@ -249,9 +249,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_freebsd.c +1 -2
index 953e371bee..33a0925c43 100644
@@ -5,8 +5,7 @@
 #include <rte_common.h>
 #include "log_internal.h"
 
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
-	return 0;
 }
lib/log/log_internal.h +1 -1
index cb15cdff08..d5fabd7ef7 100644
@@ -14,7 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id);
+void eal_log_init(const char *id);
 
 /*
  * Determine where log data is written when no call to rte_openlog_stream.
lib/log/log_syslog.c +6 -8
index c1f25d2686..ce34fa4f22 100644
@@ -81,18 +81,16 @@ static cookie_io_functions_t log_syslog_func = {
  * set the log to default function, called during eal init process,
  * once memzones are available.
  */
-int
+void
 eal_log_init(const char *id)
 {
 	FILE *log_stream;
 
-	log_stream = fopencookie(NULL, "w+", log_syslog_func);
-	if (log_stream == NULL)
-		return -1;
-
 	openlog(id, LOG_NDELAY | LOG_PID | LOG_PERROR, log_facility);
 
-	eal_log_set_default(log_stream);
-
-	return 0;
+	log_stream = fopencookie(NULL, "w+", log_syslog_func);
+	if (log_stream != NULL)
+		eal_log_set_default(log_stream);
+	else
+		eal_log_set_default(stderr);
 }
lib/log/log_windows.c +1 -3
index a3a756351d..d7c30e4cfa 100644
@@ -13,12 +13,10 @@ eal_log_syslog(const char *name __rte_unused)
 }
 
 /* set the log to default function, called during eal init process. */
-int
+void
 eal_log_init(__rte_unused const char *id)
 {
 	rte_openlog_stream(stderr);
 
 	eal_log_set_default(stderr);
-
-	return 0;
 }
Signature · 1 line
2.45.2
#394 lore raw

PATCH v27 9/14 log: add hook for printing log messages

In reply to Stephen Hemminger

This is useful for when decorating log output for console or journal. Provide basic version in this patch.

---
 lib/log/log.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
lib/log/log.c +7 -1
index d41ca2ed31..152aa634c7 100644
@@ -27,16 +27,21 @@ struct rte_log_dynamic_type {
 	uint32_t loglevel;
 };
 
+/* Note: same as vfprintf() */
+typedef int (*log_print_t)(FILE *f, const char *fmt, va_list ap);
+
 /** The rte_log structure. */
 static struct rte_logs {
 	uint32_t type;  /**< Bitfield with enabled logs. */
 	uint32_t level; /**< Log level. */
 	FILE *file;     /**< Output file set by rte_openlog_stream, or NULL. */
+	log_print_t print_func;
 	size_t dynamic_types_len;
 	struct rte_log_dynamic_type *dynamic_types;
 } rte_logs = {
 	.type = UINT32_MAX,
 	.level = RTE_LOG_DEBUG,
+	.print_func = vfprintf,
 };
 
 struct rte_eal_opt_loglevel {
@@ -78,6 +83,7 @@ int
 rte_openlog_stream(FILE *f)
 {
 	rte_logs.file = f;
+	rte_logs.print_func = vfprintf;
 	return 0;
 }
 
@@ -484,7 +490,7 @@ rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap)
 	RTE_PER_LCORE(log_cur_msg).loglevel = level;
 	RTE_PER_LCORE(log_cur_msg).logtype = logtype;
 
-	ret = vfprintf(f, format, ap);
+	ret = (*rte_logs.print_func)(f, format, ap);
 	fflush(f);
 	return ret;
 }
Signature · 1 line
2.45.2
#395 lore raw

PATCH v27 10/14 log: modify syslog handling

In reply to Stephen Hemminger

Log to syslog only if option is specified.
If no --syslog is given then use console only.

---
 app/test/test_eal_flags.c                     | 16 +++----
 doc/guides/linux_gsg/linux_eal_parameters.rst | 27 ------------
 doc/guides/prog_guide/log_lib.rst             |  5 +--
 lib/eal/common/eal_common_options.c           |  4 +-
 lib/log/log.c                                 | 43 +++++++++----------
 lib/log/log_freebsd.c                         | 11 -----
 lib/log/log_internal.h                        |  6 ---
 lib/log/log_private.h                         | 10 +++++
 lib/log/log_syslog.c                          | 21 ++++-----
 lib/log/log_windows.c                         | 22 ----------
 lib/log/version.map                           |  3 +-
 11 files changed, 51 insertions(+), 117 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_private.h
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +8 -8
index 71d8dba731..9fcf0d56e6 100644
@@ -985,12 +985,12 @@ test_misc_flags(void)
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog=user"};
+	/* With empty --syslog (now defaults) */
 	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* 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};
@@ -1080,15 +1080,15 @@ test_misc_flags(void)
 #endif
 
 	if (launch_proc(argv3) != 0) {
-		printf("Error - process did not run ok with --syslog flag\n");
+		printf("Error - process did not run ok with --syslog=user flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
-		printf("Error - process run ok with invalid --syslog flag\n");
+		printf("Error - process run ok with --syslog=invalid flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv7) != 0) {
doc/guides/linux_gsg/linux_eal_parameters.rst +0 -27
index ea8f381391..d86f94d8a8 100644
@@ -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
doc/guides/prog_guide/log_lib.rst +2 -3
index ff9d1b54a2..c87830ac00 100644
@@ -5,9 +5,7 @@ Log Library
 ===========
 
 The DPDK Log library provides the logging functionality for other DPDK libraries and drivers.
-By default, in a Linux application, logs are sent to syslog and also to the console.
-On FreeBSD and Windows applications, logs are sent only to the console.
-However, the log function can be overridden by the user to use a different logging mechanism.
+The messages can be sent to one or more sources controlled by the EAL command line options.
 
 Log Levels
 ----------
@@ -59,6 +57,7 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +2 -2
index 71c672e93e..ca7b702e03 100644
@@ -91,7 +91,7 @@ eal_long_options[] = {
 	{OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
 	{OPT_SOCKET_LIMIT,      1, NULL, OPT_SOCKET_LIMIT_NUM     },
 #ifndef RTE_EXEC_ENV_WINDOWS
-	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
+	{OPT_SYSLOG,            2, NULL, OPT_SYSLOG_NUM           },
 #endif
 	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
 	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
@@ -2209,7 +2209,7 @@ eal_common_usage(void)
 	       "  --"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"            Set syslog facility\n"
+	       "  --"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"
lib/log/log.c +20 -23

89 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -11
deleted file mode 100644
index 33a0925c43..0000000000
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-void
-eal_log_init(__rte_unused const char *id)
-{
-}
lib/log/log_internal.h +0 -6
index d5fabd7ef7..3c46328e7b 100644
@@ -16,12 +16,6 @@
 __rte_internal
 void eal_log_init(const char *id);
 
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
-
 /*
  * Save a log option for later.
  */
lib/log/log_private.h new file +10 -0
new file mode 100644
index 0000000000..43e7ff7b01
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+#ifndef RTE_EXEC_ENV_WINDOWS
+FILE *log_syslog_open(const char *id);
+#endif
+
+#endif /* LOG_PRIVATE_H */
lib/log/log_syslog.c +8 -13
index ce34fa4f22..4a05835068 100644
@@ -5,12 +5,16 @@
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
+#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 int log_facility = LOG_DAEMON;
 
@@ -77,20 +81,11 @@ static cookie_io_functions_t log_syslog_func = {
 	.close = log_syslog_close,
 };
 
-/*
- * set the log to default function, called during eal init process,
- * once memzones are available.
- */
-void
-eal_log_init(const char *id)
+FILE *
+log_syslog_open(const char *id)
 {
-	FILE *log_stream;
-
 	openlog(id, LOG_NDELAY | LOG_PID | LOG_PERROR, log_facility);
 
-	log_stream = fopencookie(NULL, "w+", log_syslog_func);
-	if (log_stream != NULL)
-		eal_log_set_default(log_stream);
-	else
-		eal_log_set_default(stderr);
+	/* redirect other log messages to syslog as well */
+	return fopencookie(NULL, "w", log_syslog_func);
 }
lib/log/log_windows.c deleted +0 -22
deleted file mode 100644
index d7c30e4cfa..0000000000
@@ -1,22 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-int
-eal_log_syslog(const char *name __rte_unused)
-{
-	return -1; /* not used */
-}
-
-/* set the log to default function, called during eal init process. */
-void
-eal_log_init(__rte_unused const char *id)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-}
lib/log/version.map +1 -2
index 879567ba15..1637fba3b9 100644
@@ -29,7 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
-	eal_log_syslog;
+	eal_log_syslog; # WINDOWS_NO_EXPORT
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#396 lore raw

PATCH v27 11/14 log: add timestamp option

In reply to Stephen Hemminger

When debugging driver or startup issues, it is useful to have a timestamp on each message printed. The messages in syslog already have a timestamp, but often syslog is not available during testing.

There are multiple timestamp formats similar to Linux dmesg. The default is time relative since startup (when first step of logging initialization is done by constructor). Other alternative formats are delta, ctime, reltime and iso formats.

Example:

$ dpdk-testpmd --log-timestamp -- -i
[     0.008610] EAL: Detected CPU lcores: 8
[     0.008634] EAL: Detected NUMA nodes: 1
[     0.008792] EAL: Detected static linkage of DPDK
[     0.010620] EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
[     0.012618] EAL: Selected IOVA mode 'VA'
[     0.016675] testpmd: No probed ethernet devices
Interactive-mode selected
---
 app/test/test_eal_flags.c           |  26 +++
 doc/guides/prog_guide/log_lib.rst   |  30 +++-
 lib/eal/common/eal_common_options.c |  14 +-
 lib/eal/common/eal_options.h        |   2 +
 lib/eal/freebsd/eal.c               |   6 +-
 lib/eal/linux/eal.c                 |   4 +-
 lib/eal/windows/eal.c               |   4 +-
 lib/log/log.c                       |   5 +
 lib/log/log_internal.h              |   9 +
 lib/log/log_private.h               |   6 +
 lib/log/log_timestamp.c             | 245 ++++++++++++++++++++++++++++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 13 files changed, 346 insertions(+), 7 deletions(-)
 create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
index 9fcf0d56e6..e24630edde 100644
@@ -1055,6 +1055,19 @@ test_misc_flags(void)
 	const char * const argv22[] = {prgname, prefix, mp_flag,
 				       "--huge-worker-stack=512"};
 
+	/* Try running with --log-timestamp */
+	const char * const argv23[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp" };
+
+	/* Try running with --log-timestamp=iso */
+	const char * const argv24[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=iso" };
+
+	/* Try running with invalid timestamp */
+	const char * const argv25[] = {prgname, prefix, mp_flag,
+				       "--log-timestamp=invalid" };
+
+
 	/* run all tests also applicable to FreeBSD first */
 
 	if (launch_proc(argv0) == 0) {
@@ -1162,6 +1175,19 @@ test_misc_flags(void)
 		printf("Error - process did not run ok with --huge-worker-stack=size parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv23) != 0) {
+		printf("Error - process did not run ok with --log-timestamp parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv24) != 0) {
+		printf("Error - process did not run ok with --log-timestamp=iso parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv25) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
+
 
 	rmdir(hugepath_dir3);
 	rmdir(hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +29 -1
index c87830ac00..82d3b7be2b 100644
@@ -57,7 +57,6 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
-
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
@@ -109,3 +108,32 @@ Throughout the cfgfile library, all logging calls are therefore of the form:
 
 	CFG_LOG(ERR, "invalid comment characters %c",
 	       params->comment_character);
+
+Log timestamp
+~~~~~~~~~~~~~
+
+An optional timestamp can be added before each message
+by adding the ``--log-timestamp`` option.
+For example::
+
+	/path/to/app --log-level=lib.*:debug --log-timestamp
+
+Multiple timestamp alternative timestamp formats are available:
+
+.. csv-table:: Log time stamp format
+   :header: "Format", "Description", "Example"
+   :widths: 6, 30, 32
+
+   "ctime", "Unix ctime", "``[Wed Mar 20 07:26:12 2024]``"
+   "delta", "Offset since last", "``[<    3.162373>]``"
+   "reltime", "Seconds since last or time if minute changed", "``[  +3.001791]`` or ``[Mar20 07:26:12]``"
+   "iso", "ISO-8601", "``[2024-03-20T07:26:12−07:00]``"
+
+To prefix all console messages with ISO format time the syntax is::
+
+	/path/to/app --log-timestamp=iso
+
+.. note::
+
+   Timestamp option has no effect if using syslog because the ``syslog()``
+   service already does timestamping internally.
lib/eal/common/eal_common_options.c +12 -2
index ca7b702e03..a70d63479a 100644
@@ -74,6 +74,7 @@ eal_long_options[] = {
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
 	{OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
 	{OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
@@ -1618,6 +1619,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		switch (opt) {
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
+		case OPT_LOG_TIMESTAMP_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1840,7 +1842,7 @@ eal_parse_common_option(int opt, const char *optarg,
 		break;
 #endif
 
-	case OPT_LOG_LEVEL_NUM: {
+	case OPT_LOG_LEVEL_NUM:
 		if (eal_parse_log_level(optarg) < 0) {
 			EAL_LOG(ERR,
 				"invalid parameters for --"
@@ -1848,7 +1850,14 @@ eal_parse_common_option(int opt, const char *optarg,
 			return -1;
 		}
 		break;
-	}
+
+	case OPT_LOG_TIMESTAMP_NUM:
+		if (eal_log_timestamp(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_TIMESTAMP);
+			return -1;
+		}
+		break;
 
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
@@ -2215,6 +2224,7 @@ eal_common_usage(void)
 	       "  --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
+	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index f3f2e104f6..e24c9eca53 100644
@@ -35,6 +35,8 @@ enum {
 	OPT_LCORES_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
+#define OPT_LOG_TIMESTAMP     "log-timestamp"
+	OPT_LOG_TIMESTAMP_NUM,
 #define OPT_TRACE             "trace"
 	OPT_TRACE_NUM,
 #define OPT_TRACE_DIR         "trace-dir"
lib/eal/freebsd/eal.c +4 -2
index 118c1f593b..06bccbd026 100644
@@ -392,8 +392,10 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled these */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -1
index 62d3d281c4..cf2f0fcab9 100644
@@ -611,7 +611,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/windows/eal.c +3 -1
index 33f044d7cc..b1c59945fb 100644
@@ -121,7 +121,9 @@ eal_parse_args(int argc, char **argv)
 		}
 
 		/* eal_log_level_parse() already handled these options */
-		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
+		if (opt == OPT_LOG_LEVEL_NUM ||
+		    opt == OPT_SYSLOG_NUM ||
+		    opt == OPT_LOG_TIMESTAMP_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/log/log.c +5 -0
index b863a0b6bc..5455687e79 100644
@@ -514,6 +514,11 @@ eal_log_init(const char *id)
 		rte_openlog_stream(logf);
 #endif
 
+	if (log_timestamp_enabled())
+		rte_logs.print_func = log_print_with_timestamp;
+	else
+		rte_logs.print_func = vfprintf;
+
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
 		"Debug dataplane logs available - lower performance\n");
lib/log/log_internal.h +9 -0
index 3c46328e7b..7c7d44eed2 100644
@@ -5,8 +5,10 @@
 #ifndef LOG_INTERNAL_H
 #define LOG_INTERNAL_H
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <time.h>
 
 #include <rte_compat.h>
 
@@ -39,4 +41,11 @@ const char *eal_log_level2str(uint32_t level);
 __rte_internal
 void rte_eal_log_cleanup(void);
 
+/*
+ * Add timestamp to console logs
+ */
+__rte_internal
+int eal_log_timestamp(const char *fmt);
+
+
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +6 -0
index 43e7ff7b01..53d05f8ac8 100644
@@ -7,4 +7,10 @@
 FILE *log_syslog_open(const char *id);
 #endif
 
+bool log_timestamp_enabled(void);
+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);
+
 #endif /* LOG_PRIVATE_H */
lib/log/log_timestamp.c new file +245 -0

245 lines not on this page · raw message

lib/log/meson.build +1 -0
index 160cf34f50..4ac232786e 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_timestamp.c',
 )
 
 if not is_windows
lib/log/version.map +1 -0
index 1637fba3b9..8be6907840 100644
@@ -30,5 +30,6 @@ INTERNAL {
 	eal_log_save_pattern;
 	eal_log_save_regexp;
 	eal_log_syslog; # WINDOWS_NO_EXPORT
+	eal_log_timestamp;
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#397 lore raw

PATCH v27 12/14 log: add support for systemd journal

In reply to Stephen Hemminger

If DPDK application is being run as a systemd service, then it can use the journal protocol which allows putting more information in the log such as priority and other information.

The use of journal protocol is automatically detected and handled. Rather than having a dependency on libsystemd, just use the protocol directly as defined in:
https://systemd.io/JOURNAL_NATIVE_PROTOCOL/

---
 lib/log/log.c          |  13 ++--
 lib/log/log_internal.h |   3 +
 lib/log/log_journal.c  | 154 +++++++++++++++++++++++++++++++++++++++++
 lib/log/log_private.h  |  14 +++-
 lib/log/log_syslog.c   |  17 ++++-
 lib/log/meson.build    |   4 ++
 lib/log/version.map    |   1 +
 7 files changed, 198 insertions(+), 8 deletions(-)
 create mode 100644 lib/log/log_journal.c
lib/log/log.c +7 -6
index 5455687e79..343f9d77b7 100644
@@ -506,15 +506,16 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)
 void
 eal_log_init(const char *id)
 {
-#ifndef RTE_EXEC_ENV_WINDOWS
-	FILE *logf;
+	FILE *logf = NULL;
+
+	if (log_journal_enabled())
+		logf = log_journal_open(id);
+	else if (log_syslog_enabled())
+		logf = log_syslog_open(id);
 
-	logf = log_syslog_open(id);
 	if (logf)
 		rte_openlog_stream(logf);
-#endif
-
-	if (log_timestamp_enabled())
+	else if (log_timestamp_enabled())
 		rte_logs.print_func = log_print_with_timestamp;
 	else
 		rte_logs.print_func = vfprintf;
lib/log/log_internal.h +3 -0
index 7c7d44eed2..82fdc21ac2 100644
@@ -29,6 +29,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t level);
 __rte_internal
 int eal_log_syslog(const char *name);
 
+__rte_internal
+int eal_log_journal(const char *opt);
+
 /*
  * Convert log level to string.
  */
lib/log/log_journal.c new file +154 -0

154 lines not on this page · raw message

lib/log/log_private.h +13 -1
index 53d05f8ac8..625f57c0cc 100644
@@ -3,10 +3,22 @@
 #ifndef LOG_PRIVATE_H
 #define LOG_PRIVATE_H
 
-#ifndef RTE_EXEC_ENV_WINDOWS
+#ifdef RTE_EXEC_ENV_WINDOWS
+#define log_syslog_enabled()  (false)
+#define log_syslog_open(id)   (NULL)
+#else
+bool log_syslog_enabled(void);
 FILE *log_syslog_open(const char *id);
 #endif
 
+#ifdef RTE_EXEC_ENV_LINUX
+bool log_journal_enabled(void);
+FILE *log_journal_open(const char *id);
+#else
+#define log_journal_enabled() (false)
+#define log_journal_open(id)  (NULL)
+#endif /* !RTE_EXEC_ENV_LINUX */
+
 bool log_timestamp_enabled(void);
 ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);
 
lib/log/log_syslog.c +16 -1
index 4a05835068..d911deff44 100644
@@ -16,8 +16,12 @@
 #include "log_internal.h"
 #include "log_private.h"
 
-static int log_facility = LOG_DAEMON;
+static int log_facility;
 
+/*
+ * Usable list of facilities
+ * Skip kern, mark, and security
+ */
 static const struct {
 	const char *name;
 	int value;
@@ -48,6 +52,11 @@ eal_log_syslog(const char *name)
 {
 	unsigned int i;
 
+	if (name == NULL) {
+		log_facility = LOG_DAEMON;
+		return 0;
+	}
+
 	for (i = 0; i < RTE_DIM(facilitys); i++) {
 		if (!strcmp(name, facilitys[i].name)) {
 			log_facility = facilitys[i].value;
@@ -57,6 +66,12 @@ eal_log_syslog(const char *name)
 	return -1;
 }
 
+/* syslog is enabled if facility is set */
+bool log_syslog_enabled(void)
+{
+	return log_facility != 0; /* LOG_KERN is 0 */
+}
+
 /*
  * default log function
  */
lib/log/meson.build +4 -0
index 4ac232786e..86e4452b19 100644
@@ -11,4 +11,8 @@ if not is_windows
     sources += files('log_syslog.c')
 endif
 
+if is_linux
+    sources += files('log_journal.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -0
index 8be6907840..800d3943bc 100644
@@ -26,6 +26,7 @@ INTERNAL {
 	global:
 
 	eal_log_init;
+	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
Signature · 1 line
2.45.2
#398 lore raw

PATCH v27 13/14 log: colorize log output

In reply to Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

The default is to not use color since it may disturb automatic tests and other embedded usage.

---
 app/test/test_eal_flags.c           |  24 ++++
 doc/guides/prog_guide/log_lib.rst   |  24 ++++
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |  20 ++-
 lib/log/log_color.c                 | 216 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 308 insertions(+), 4 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
index e24630edde..cd73711da6 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
 	const char * const argv25[] = {prgname, prefix, mp_flag,
 				       "--log-timestamp=invalid" };
 
+	/* Try running with --log-color */
+	const char * const argv26[] = {prgname, prefix, mp_flag,
+				       "--log-color" };
+
+	/* Try running with --log-color=never */
+	const char * const argv27[] = {prgname, prefix, mp_flag,
+				       "--log-color=never" };
+
+	/* Try running with --log-color=invalid */
+	const char * const argv28[] = {prgname, prefix, mp_flag,
+				       "--log-color=invalid" };
+
 
 	/* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
 		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
 		goto fail;
 	}
+	if (launch_proc(argv26) != 0) {
+		printf("Error - process did not run ok with --log-color parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv27) != 0) {
+		printf("Error - process did not run ok with --log-color=none parameter\n");
+		goto fail;
+	}
+	if (launch_proc(argv28) == 0) {
+		printf("Error - process did run ok with --log-timestamp=invalid parameter\n");
+		goto fail;
+	}
 
 
 	rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +24 -0
index 82d3b7be2b..a4f880037b 100644
@@ -57,6 +57,7 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
@@ -137,3 +138,26 @@ To prefix all console messages with ISO format time the syntax is::
 
    Timestamp option has no effect if using syslog because the ``syslog()``
    service already does timestamping internally.
+
+
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+The optional argument describes when color is enabled:
+
+:never: Do not enable color. This is the default behavior.
+
+:auto: Enable color only when printing to a terminal.
+       This is the same as ``--log-color`` with no argument
+
+:always: Always print color
+
+For example to enable color in logs if using terminal::
+
+	/path/to/app --log-color
+
+.. note::
+
+   Color output is never used for syslog or systemd journal logging.
lib/eal/common/eal_common_options.c +11 -0
index a70d63479a..6965666a7c 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
 	{OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
 	{OPT_IOVA_MODE,	        1, NULL, OPT_IOVA_MODE_NUM        },
 	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+	{OPT_LOG_COLOR,		2, NULL, OPT_LOG_COLOR_NUM	  },
 	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
 	{OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
 	{OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
 		case OPT_LOG_LEVEL_NUM:
 		case OPT_SYSLOG_NUM:
 		case OPT_LOG_TIMESTAMP_NUM:
+		case OPT_LOG_COLOR_NUM:
 			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
 				return -1;
 			break;
@@ -1859,6 +1861,14 @@ eal_parse_common_option(int opt, const char *optarg,
 		}
 		break;
 
+	case OPT_LOG_COLOR_NUM:
+		if (eal_log_color(optarg) < 0) {
+			EAL_LOG(ERR, "invalid parameters for --"
+				OPT_LOG_COLOR);
+			return -1;
+		}
+		break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
 	case OPT_TRACE_NUM: {
 		if (eal_trace_args_save(optarg) < 0) {
@@ -2225,6 +2235,7 @@ eal_common_usage(void)
 	       "                      Set specific log level\n"
 	       "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
 	       "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+	       "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
 	       "  --"OPT_TRACE"=<regex-match>\n"
 	       "                      Enable trace based on regular expression trace name.\n"
lib/eal/common/eal_options.h +2 -0
index e24c9eca53..87c3c32f86 100644
@@ -33,6 +33,8 @@ enum {
 	OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
 	OPT_LCORES_NUM,
+#define OPT_LOG_COLOR	      "log-color"
+	OPT_LOG_COLOR_NUM,
 #define OPT_LOG_LEVEL         "log-level"
 	OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
lib/log/log.c +16 -4
index 343f9d77b7..f1bd408bee 100644
@@ -515,10 +515,22 @@ eal_log_init(const char *id)
 
 	if (logf)
 		rte_openlog_stream(logf);
-	else if (log_timestamp_enabled())
-		rte_logs.print_func = log_print_with_timestamp;
-	else
-		rte_logs.print_func = vfprintf;
+	else {
+		bool is_terminal = isatty(fileno(stderr));
+		bool use_color = log_color_enabled(is_terminal);
+
+		if (log_timestamp_enabled()) {
+			if (use_color)
+				rte_logs.print_func = color_print_with_timestamp;
+			else
+				rte_logs.print_func = log_print_with_timestamp;
+		} else {
+			if (use_color)
+				rte_logs.print_func = color_print;
+			else
+				rte_logs.print_func = vfprintf;
+		}
+	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	RTE_LOG(NOTICE, EAL,
lib/log/log_color.c new file +216 -0

216 lines not on this page · raw message

lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index 625f57c0cc..42babbcac1 100644
@@ -25,4 +25,12 @@ 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_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 86e4452b19..b3de57b9c7 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -0
index 800d3943bc..09d8a4289b 100644
@@ -25,6 +25,7 @@ DPDK_25 {
 INTERNAL {
 	global:
 
+	eal_log_color;
 	eal_log_init;
 	eal_log_journal; # WINDOWS_NO_EXPORT
 	eal_log_level2str;
Signature · 1 line
2.45.2
#399 lore raw

Re: [PATCH v27 13/14] log: colorize log output

The code has some mentions of --log-color=none but only the never option is parsed.

Quoted 490 lines · Stephen Hemminger

Like dmesg, colorize the log output (unless redirected to file). Timestamp is green, the subsystem is in yellow and the message is red if urgent, boldface if an error, and normal for info and debug messages.

The default is to not use color since it may disturb automatic tests and other embedded usage.

---
 app/test/test_eal_flags.c           |  24 ++++
 doc/guides/prog_guide/log_lib.rst   |  24 ++++
 lib/eal/common/eal_common_options.c |  11 ++
 lib/eal/common/eal_options.h        |   2 +
 lib/log/log.c                       |  20 ++-
 lib/log/log_color.c                 | 216 ++++++++++++++++++++++++++++
 lib/log/log_internal.h              |   5 +
 lib/log/log_private.h               |   8 ++
 lib/log/meson.build                 |   1 +
 lib/log/version.map                 |   1 +
 10 files changed, 308 insertions(+), 4 deletions(-)
 create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -3
index e24630edde..cd73711da6 100644
@@ -1067,6 +1067,18 @@ test_misc_flags(void)
        const char * const argv25[] = {prgname, prefix, mp_flag,
                                       "--log-timestamp=invalid" };
 
+       /* Try running with --log-color */
+       const char * const argv26[] = {prgname, prefix, mp_flag,
+                                      "--log-color" };
+
+       /* Try running with --log-color=never */
+       const char * const argv27[] = {prgname, prefix, mp_flag,
+                                      "--log-color=never" };
+
+       /* Try running with --log-color=invalid */
+       const char * const argv28[] = {prgname, prefix, mp_flag,
+                                      "--log-color=invalid" };
+
 
        /* run all tests also applicable to FreeBSD first */
 
@@ -1187,6 +1199,18 @@ test_misc_flags(void)
                printf("Error - process did run ok with
--log-timestamp=invalid parameter\n");
                goto fail;
        }
+       if (launch_proc(argv26) != 0) {
+               printf("Error - process did not run ok with --log-color
 parameter\n");
+               goto fail;
+       }
+       if (launch_proc(argv27) != 0) {
+               printf("Error - process did not run ok with
--log-color=none parameter\n");
+               goto fail;
+       }
+       if (launch_proc(argv28) == 0) {
+               printf("Error - process did run ok with
--log-timestamp=invalid parameter\n");
+               goto fail;
+       }
 
 
        rmdir(hugepath_dir3);
doc/guides/prog_guide/log_lib.rst +0 -0
index 82d3b7be2b..a4f880037b 100644
@@ -57,6 +57,7 @@ For example::
 
 Within an application, the same result can be got using the

``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.

doc/guides/prog_guide/log_lib.rst +1 -0
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
@@ -137,3 +138,26 @@ To prefix all console messages with ISO format time

the syntax is::

Timestamp option has no effect if using syslog because the ``syslog()`` service already does timestamping internally.

doc/guides/prog_guide/log_lib.rst +23 -0
+
+
+Color output
+~~~~~~~~~~~~
+
+The log library will highlight important messages.
+This is controlled by the ``--log-color`` option.
+The optional argument describes when color is enabled:
+
+:never: Do not enable color. This is the default behavior.
+
+:auto: Enable color only when printing to a terminal.
+       This is the same as ``--log-color`` with no argument
+
+:always: Always print color
+
+For example to enable color in logs if using terminal::
+
+       /path/to/app --log-color
+
+.. note::
+
+   Color output is never used for syslog or systemd journal logging.
lib/eal/common/eal_common_options.c +2 -0
index a70d63479a..6965666a7c 100644
@@ -73,6 +73,7 @@ eal_long_options[] = {
        {OPT_HUGE_UNLINK,       2, NULL, OPT_HUGE_UNLINK_NUM      },
        {OPT_IOVA_MODE,         1, NULL, OPT_IOVA_MODE_NUM        },
        {OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
+       {OPT_LOG_COLOR,         2, NULL, OPT_LOG_COLOR_NUM        },
        {OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
        {OPT_LOG_TIMESTAMP,     2, NULL, OPT_LOG_TIMESTAMP_NUM    },
        {OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
@@ -1620,6 +1621,7 @@ eal_log_level_parse(int argc, char * const argv[])
                case OPT_LOG_LEVEL_NUM:
                case OPT_SYSLOG_NUM:
                case OPT_LOG_TIMESTAMP_NUM:
+               case OPT_LOG_COLOR_NUM:
                        if (eal_parse_common_option(opt, optarg,
 internal_conf) < 0)
                                return -1;
                        break;
lib/eal/common/eal_common_options.c +9 -0
@@ -1859,6 +1861,14 @@ eal_parse_common_option(int opt, const char *optarg,
                }
                break;
 
+       case OPT_LOG_COLOR_NUM:
+               if (eal_log_color(optarg) < 0) {
+                       EAL_LOG(ERR, "invalid parameters for --"
+                               OPT_LOG_COLOR);
+                       return -1;
+               }
+               break;
+
 #ifndef RTE_EXEC_ENV_WINDOWS
        case OPT_TRACE_NUM: {
                if (eal_trace_args_save(optarg) < 0) {
@@ -2225,6 +2235,7 @@ eal_common_usage(void)
               "                      Set specific log level\n"
               "  --"OPT_LOG_LEVEL"=help    Show log types and levels\n"
               "  --"OPT_LOG_TIMESTAMP"[=<format>]  Timestamp log output\n"
+              "  --"OPT_LOG_COLOR"[=<when>] Colorize log messages\n"
 #ifndef RTE_EXEC_ENV_WINDOWS
               "  --"OPT_TRACE"=<regex-match>\n"
               "                      Enable trace based on regular

expression trace name.\n"

lib/eal/common/eal_options.h +2 -0
index e24c9eca53..87c3c32f86 100644
@@ -33,6 +33,8 @@ enum {
        OPT_HUGE_UNLINK_NUM,
 #define OPT_LCORES            "lcores"
        OPT_LCORES_NUM,
+#define OPT_LOG_COLOR        "log-color"
+       OPT_LOG_COLOR_NUM,
 #define OPT_LOG_LEVEL         "log-level"
        OPT_LOG_LEVEL_NUM,
 #define OPT_LOG_TIMESTAMP     "log-timestamp"
lib/log/log.c +16 -4
index 343f9d77b7..f1bd408bee 100644
@@ -515,10 +515,22 @@ eal_log_init(const char *id)
 
        if (logf)
                rte_openlog_stream(logf);
-       else if (log_timestamp_enabled())
-               rte_logs.print_func = log_print_with_timestamp;
-       else
-               rte_logs.print_func = vfprintf;
+       else {
+               bool is_terminal = isatty(fileno(stderr));
+               bool use_color = log_color_enabled(is_terminal);
+
+               if (log_timestamp_enabled()) {
+                       if (use_color)
+                               rte_logs.print_func =
 color_print_with_timestamp;
+                       else
+                               rte_logs.print_func =
 log_print_with_timestamp;
+               } else {
+                       if (use_color)
+                               rte_logs.print_func = color_print;
+                       else
+                               rte_logs.print_func = vfprintf;
+               }
+       }
 

#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
RTE_LOG(NOTICE, EAL,

lib/log/log_color.c new file +122 -0
new file mode 100644
index 0000000000..82a9ac8022
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+#include <rte_os_shim.h>
+#endif
+
+#include "log_internal.h"
+#include "log_private.h"
+
+enum  {
+       LOG_COLOR_AUTO = 0,
+       LOG_COLOR_NEVER,
+       LOG_COLOR_ALWAYS,
+} log_color_mode = LOG_COLOR_NEVER;
+
+enum color {
+       COLOR_NONE,
+       COLOR_RED,
+       COLOR_GREEN,
+       COLOR_YELLOW,
+       COLOR_BLUE,
+       COLOR_MAGENTA,
+       COLOR_CYAN,
+       COLOR_WHITE,
+       COLOR_BOLD,
+       COLOR_CLEAR,
+};
+
+enum log_field {
+       LOG_FIELD_SUBSYS,
+       LOG_FIELD_TIME,
+       LOG_FIELD_ALERT,
+       LOG_FIELD_ERROR,
+       LOG_FIELD_INFO,
+};
+
+static const enum color field_colors[] = {
+       [LOG_FIELD_SUBSYS] = COLOR_YELLOW,
+       [LOG_FIELD_TIME]   = COLOR_GREEN,
+       [LOG_FIELD_ALERT]  = COLOR_RED,
+       [LOG_FIELD_ERROR]  = COLOR_BOLD,
+       [LOG_FIELD_INFO]   = COLOR_NONE,
+};
+
+/* If set all colors are bolder */
+static bool dark_mode;
+
+/* Standard terminal escape codes for colors and bold */
+static const uint8_t color_esc_code[] = {
+       [COLOR_RED]     = 31,
+       [COLOR_GREEN]   = 32,
+       [COLOR_YELLOW]  = 33,
+       [COLOR_BLUE]    = 34,
+       [COLOR_MAGENTA] = 35,
+       [COLOR_CYAN]    = 36,
+       [COLOR_WHITE]   = 37,
+       [COLOR_BOLD]    = 1,
+};
+
+__rte_format_printf(4, 5)
+static int
+color_snprintf(char *buf, size_t len, enum log_field field,
+              const char *fmt, ...)
+{
+       enum color color = field_colors[field];
+       uint8_t esc = color_esc_code[color];
+       va_list args;
+       int ret = 0;
+
+       va_start(args, fmt);
+       if (esc == 0) {
+               ret = vsnprintf(buf, len, fmt, args);
+       } else {
+               ret = snprintf(buf, len,
+                              dark_mode ? "\e[1;%um" : "\e[%um", esc);
+               ret += vsnprintf(buf + ret, len - ret, fmt, args);
+               ret += snprintf(buf + ret,  len - ret, "%s", "\e[0m");
+       }
+       va_end(args);
+
+       return ret;
+}
+
+/*
+ * Controls whether color is enabled:
+ * modes are:
+ *   always - enable color output regardless
+ *   auto - enable if stderr is a terminal
+ *   never - color output is disabled.
+ */
+int
+eal_log_color(const char *mode)
+{
+       if (mode == NULL || strcmp(mode, "always") == 0)
+               log_color_mode = LOG_COLOR_ALWAYS;
+       else if (strcmp(mode, "never") == 0)
+               log_color_mode = LOG_COLOR_NEVER;
+       else if (strcmp(mode, "auto") == 0)
+               log_color_mode = LOG_COLOR_AUTO;
+       else
+               return -1;
+
+       return 0;
+}
+
+bool
+log_color_enabled(bool is_terminal)
+{
+       char *env, *sep;
+
+       /* Set dark mode using the defacto heuristics used by other

programs */

lib/log/log_color.c new file +48 -0
+       env = getenv("COLORFGBG");
+       if (env) {
+               sep = strrchr(env, ';');
+               if (sep &&
+                   ((sep[1] >= '0' && sep[1] <= '6') || sep[1] == '8') &&
+                   sep[2] == '\0')
+                       dark_mode = true;
+       }
+
+       switch (log_color_mode) {
+       case LOG_COLOR_ALWAYS:
+               return true;
+       case LOG_COLOR_AUTO:
+               return is_terminal;
+       default:
+               return false;
+
+       }
+}
+
+/* Look ast the current message level to determine color of field */
+static enum log_field
+color_msg_field(void)
+{
+       const int level = rte_log_cur_msg_loglevel();
+
+       if (level <= 0 || level >= (int)RTE_LOG_INFO)
+               return LOG_FIELD_INFO;
+       else if (level >= (int)RTE_LOG_ERR)
+               return LOG_FIELD_ERROR;
+       else
+               return LOG_FIELD_ALERT;
+}
+
+__rte_format_printf(3, 0)
+static int
+color_fmt_msg(char *out, size_t len, const char *format, va_list ap)
+{
+       enum log_field field = color_msg_field();
+       char buf[LINE_MAX];
+       int ret = 0;
+
+       /* format raw message */
+       vsnprintf(buf, sizeof(buf), format, ap);
+       const char *msg = buf;
+
+       /*
+        * use convention that first part of message (up to the ':'

character)

lib/log/log_color.c new file +46 -0
+        * is the subsystem id and should be highlighted.
+        */
+       const char *cp = strchr(msg, ':');
+       if (cp) {
+               /* print first part in yellow */
+               ret = color_snprintf(out, len, LOG_FIELD_SUBSYS,
+                                    "%.*s", (int)(cp - msg + 1), msg);
+               msg = cp + 1;
+       }
+
+       ret += color_snprintf(out + ret, len - ret, field, "%s", msg);
+       return ret;
+}
+
+__rte_format_printf(2, 0)
+int
+color_print(FILE *f, const char *format, va_list ap)
+{
+       char out[LINE_MAX];
+
+       /* format raw message */
+       int ret = color_fmt_msg(out, sizeof(out), format, ap);
+       if (fputs(out, f) < 0)
+               return -1;
+
+       return ret;
+}
+
+__rte_format_printf(2, 0)
+int
+color_print_with_timestamp(FILE *f, const char *format, va_list ap)
+{
+       char out[LINE_MAX];
+       char tsbuf[128];
+       int ret = 0;
+
+       if (log_timestamp(tsbuf, sizeof(tsbuf)) > 0)
+               ret = color_snprintf(out, sizeof(out),
+                                    LOG_FIELD_TIME, "[%s] ", tsbuf);
+
+       ret += color_fmt_msg(out + ret, sizeof(out) - ret, format, ap);
+       if (fputs(out, f) < 0)
+               return -1;
+
+       return ret;
+}
lib/log/log_internal.h +5 -0
index 82fdc21ac2..bba7041ea3 100644
@@ -50,5 +50,10 @@ void rte_eal_log_cleanup(void);
 __rte_internal
 int eal_log_timestamp(const char *fmt);
 
+/*
+ * Enable or disable color in log messages
+ */
+__rte_internal
+int eal_log_color(const char *mode);
 
 #endif /* LOG_INTERNAL_H */
lib/log/log_private.h +8 -0
index 625f57c0cc..42babbcac1 100644
@@ -25,4 +25,12 @@ 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_color_enabled(bool is_tty);
+
+__rte_format_printf(2, 0)
+int color_print(FILE *f, const char *format, va_list ap);
+
+__rte_format_printf(2, 0)
+int color_print_with_timestamp(FILE *f, const char *format, va_list ap);
+
 #endif /* LOG_PRIVATE_H */
lib/log/meson.build +1 -0
index 86e4452b19..b3de57b9c7 100644
@@ -4,6 +4,7 @@
 includes += global_inc
 sources = files(
         'log.c',
+        'log_color.c',
         'log_timestamp.c',
 )
 
lib/log/version.map +1 -1
index 800d3943bc..09d8a4289b 100644
@@ -25,6 +25,7 @@ DPDK_25 {
 INTERNAL {
        global:
 
+       eal_log_color;
        eal_log_init;
        eal_log_journal; # WINDOWS_NO_EXPORT
        eal_log_level2str;
--

2.45.2

Signature · 6 lines
Baruch Even
Platform Technical Lead at WEKA
E [email protected]* ­*W https://www.weka.io* ­*

[image: App Banner Image]
<https://www.weka.io/trends-in-AI-emsig?utm_campaign=signature&utm_source=WiseStamp&utm_medium=email>
#400 lore raw

PATCH v27 14/14 doc: add release note about log library

In reply to Stephen Hemminger

Significant enough to add some documentation.

---
 doc/guides/rel_notes/release_24_11.rst | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
doc/guides/rel_notes/release_24_11.rst +19 -0
index fa4822d928..ec4b7ba2a4 100644
@@ -349,6 +349,25 @@ API Changes
   and replaced it with a new shared devarg ``llq_policy`` that keeps the same logic.
 
 
+* **Logging library changes**
+
+  * The log is initialized earlier in startup so all messages go through the library.
+
+  * Added a new option to timestamp log messages, which is useful for
+    debugging delays in application and driver startup.
+
+  * Syslog option change. If *--syslog* is specified, then messages
+    will go to syslog; if not specified then messages will only be displayed
+    on stderr. This option is now supported on FreeBSD (but not on Windows).
+
+  * If the application is a systemd service and the log output is being
+    sent of standard error then DPDK will switch to journal native protocol.
+
+  * Log messages can be timestamped with *--log-timestamp* option.
+
+  * Log messages can be colorized with the *--log-color* option.
+
+
 ABI Changes
 -----------
 
Signature · 1 line
2.45.2
#401 lore raw

v28 cover Logging subsystem improvements

In reply to Stephen Hemminger

Improvements and unification of logging library.
This version works on all platforms: Linux, Windows and FreeBSD.

This is update to rework patch set. It adds several new features to the console log output.

* Putting a timestamp on console output which is useful for analyzing performance of startup codes. Timestamp is optional and must be enabled on command line.

* Displaying console output with colors.
It uses the standard conventions used by many other Linux commands for colorized display. The default is to enable color if the console output is going to a terminal. But it can be always on or disabled by command line flag. This default was chosen based on what dmesg(1) command does.

Color is used by many tools (vi, iproute2, git) because it is helpful; DPDK drivers and libraries print lots of not very useful messages. And having error messages highlighted in bold face helps. This might also get users to pay more attention to error messages. Many bug reports have earlier messages that are lost because there are so many info messages.

* Add support for automatic detection of systemd journal protocol. If running as systemd service will get enhanced logging.

* Use of syslog is optional and the meaning of the --syslog flag has changed. The default is *not* to use unless requested.

Add myself as maintainer for log because by now have added more than previous authors.

v28 - fix windows build
fixup documentation around syslog
consolidate syslog patches

Stephen Hemminger (13):
maintainers: add for log library
windows: make getopt functions have const properties
windows: update os shim
eal: make eal_log_level_parse common
eal: do not duplicate rte_init_alert() messages
eal: change rte_exit() output to match rte_log()
log: rework syslog handling
eal: initialize log before everything else
log: add hook for printing log messages
log: add timestamp option
log: add support for systemd journal
log: colorize log output
doc: add release note about log library

 MAINTAINERS                                   |   1 +
 app/test/test_eal_flags.c                     |  66 ++++-
 .../freebsd_gsg/freebsd_eal_parameters.rst    |  27 ++
 .../prog_guide/env_abstraction_layer.rst      |   6 +-
 doc/guides/prog_guide/log_lib.rst             |  57 ++++-
 doc/guides/rel_notes/release_24_11.rst        |  19 ++
 lib/eal/common/eal_common_debug.c             |   6 +-
 lib/eal/common/eal_common_options.c           | 122 +++++----
 lib/eal/common/eal_internal_cfg.h             |   1 -
 lib/eal/common/eal_options.h                  |   5 +
 lib/eal/freebsd/eal.c                         |  65 ++---
 lib/eal/linux/eal.c                           |  68 +----
 lib/eal/windows/eal.c                         |  50 +---
 lib/eal/windows/getopt.c                      |  23 +-
 lib/eal/windows/include/getopt.h              |   8 +-
 lib/eal/windows/include/rte_os_shim.h         |  10 +
 lib/log/log.c                                 |  76 ++++--
 lib/log/log_color.c                           | 214 ++++++++++++++++
 lib/log/log_freebsd.c                         |  12 -
 lib/log/log_internal.h                        |  22 +-
 lib/log/log_journal.c                         | 154 +++++++++++
 lib/log/log_linux.c                           |  61 -----
 lib/log/log_private.h                         |  53 ++++
 lib/log/log_syslog.c                          | 109 ++++++++
 lib/log/log_timestamp.c                       | 240 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 --
 lib/log/meson.build                           |  12 +-
 lib/log/version.map                           |   5 +-
 28 files changed, 1158 insertions(+), 352 deletions(-)
 create mode 100644 lib/log/log_color.c
 delete mode 100644 lib/log/log_freebsd.c
 create mode 100644 lib/log/log_journal.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 create mode 100644 lib/log/log_timestamp.c
 delete mode 100644 lib/log/log_windows.c
Signature · 1 line
2.45.2
#402 lore raw

PATCH v28 1/13 maintainers: add for log library

"You touch it you own it"
Add myself as maintainer for log library.

---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
index cd78bc7db1..a504b8fc54 100644
@@ -186,6 +186,7 @@ F: app/test/test_threads.c
 F: app/test/test_version.c
 
 Logging
+M: Stephen Hemminger <[email protected]>
 F: lib/log/
 F: doc/guides/prog_guide/log_lib.rst
 F: app/test/test_logs.c
Signature · 1 line
2.45.2
#403 lore raw

PATCH v28 2/13 windows: make getopt functions have const properties

In reply to Stephen Hemminger

Having different prototypes on different platforms can lead to lots of unnecessary workarounds. Looks like the version of getopt used from windows was based on an older out of date version from FreeBSD.

This patch changes getopt, getopt_long, etc to have the same const attributes as Linux and FreeBSD. The changes are derived from the current FreeBSD version of getopt_long.

---
 lib/eal/windows/getopt.c         | 23 ++++++++++++-----------
 lib/eal/windows/include/getopt.h |  8 ++++----
 2 files changed, 16 insertions(+), 15 deletions(-)
lib/eal/windows/getopt.c +12 -11
index a1f51c6c23..50ff71b930 100644
@@ -20,7 +20,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-const char    *optarg;		/* argument associated with option */
+char    *optarg;		/* argument associated with option */
 int	opterr = 1;		/* if error message should be printed */
 int	optind = 1;		/* index into parent argv vector */
 int	optopt = '?';		/* character checked for validity */
@@ -39,9 +39,9 @@ static void pass(const char *a) {(void) a; }
 #define	BADARG		((*options == ':') ? (int)':' : (int)'?')
 #define	INORDER		1
 
-#define	EMSG		""
+static char EMSG[] = "";
 
-static const char *place = EMSG; /* option letter processing */
+static char *place = EMSG; /* option letter processing */
 
 /* XXX: set optreset to 1 rather than these two */
 static int nonopt_start = -1; /* first non option argument (for permute) */
@@ -80,7 +80,7 @@ gcd(int a, int b)
  */
 static void
 permute_args(int panonopt_start, int panonopt_end, int opt_end,
-	char **nargv)
+	char * const *nargv)
 {
 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
 	char *swap;
@@ -101,11 +101,12 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
 				pos -= nnonopts;
 			else
 				pos += nopts;
+
 			swap = nargv[pos];
 			/* LINTED const cast */
-			((char **) nargv)[pos] = nargv[cstart];
+			((char **)(uintptr_t)nargv)[pos] = nargv[cstart];
 			/* LINTED const cast */
-			((char **)nargv)[cstart] = swap;
+			((char **)(uintptr_t)nargv)[cstart] = swap;
 		}
 	}
 }
@@ -116,7 +117,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  * Returns -1 if short_too is set and the option does not match long_options.
  */
 static int
-parse_long_options(char **nargv, const char *options,
+parse_long_options(char * const *nargv, const char *options,
 	const struct option *long_options, int *idx, int short_too)
 {
 	const char *current_argv;
@@ -236,7 +237,7 @@ parse_long_options(char **nargv, const char *options,
  *	Parse argc/argv argument vector.  Called by user level routines.
  */
 static int
-getopt_internal(int nargc, char **nargv, const char *options,
+getopt_internal(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx, int flags)
 {
 	char *oli;				/* option letter list index */
@@ -434,7 +435,7 @@ getopt_internal(int nargc, char **nargv, const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt(int nargc, char *nargv[], const char *options)
+getopt(int nargc, char *const nargv[], const char *options)
 {
 	return getopt_internal(nargc, nargv, options, NULL, NULL,
 			       FLAG_PERMUTE);
@@ -445,7 +446,7 @@ getopt(int nargc, char *nargv[], const char *options)
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long(int nargc, char *nargv[], const char *options,
+getopt_long(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
@@ -458,7 +459,7 @@ getopt_long(int nargc, char *nargv[], const char *options,
  *	Parse argc/argv argument vector.
  */
 int
-getopt_long_only(int nargc, char *nargv[], const char *options,
+getopt_long_only(int nargc, char *const nargv[], const char *options,
 	const struct option *long_options, int *idx)
 {
 
lib/eal/windows/include/getopt.h +4 -4
index 6f57af454b..e4cf6873cb 100644
@@ -44,7 +44,7 @@
 
 
 /** argument to current option, or NULL if it has none */
-extern const char *optarg;
+extern char *optarg;
 /** Current position in arg string.  Starts from 1.
  * Setting to 0 resets state.
  */
@@ -80,14 +80,14 @@ struct option {
 };
 
 /** Compat: getopt */
-int getopt(int argc, char *argv[], const char *options);
+int getopt(int argc, char *const argv[], const char *options);
 
 /** Compat: getopt_long */
-int getopt_long(int argc, char *argv[], const char *options,
+int getopt_long(int argc, char *const argv[], const char *options,
 		const struct option *longopts, int *longindex);
 
 /** Compat: getopt_long_only */
-int getopt_long_only(int nargc, char *argv[], const char *options,
+int getopt_long_only(int nargc, char *const argv[], const char *options,
 		     const struct option *long_options, int *idx);
 
 
Signature · 1 line
2.45.2
#404 lore raw

PATCH v28 3/13 windows: update os shim

In reply to Stephen Hemminger

Windows does not have localtime_r but it does have a similar function that can be used instead.

Use rte_os_shim.h in lib/log instead of redefine of strdup.

---
 lib/eal/windows/include/rte_os_shim.h | 10 ++++++++++
 lib/log/log.c                         |  7 +++----
 2 files changed, 13 insertions(+), 4 deletions(-)
lib/eal/windows/include/rte_os_shim.h +10 -0
index eda8113662..665c9ac93b 100644
@@ -110,4 +110,14 @@ rte_clock_gettime(clockid_t clock_id, struct timespec *tp)
 }
 #define clock_gettime(clock_id, tp) rte_clock_gettime(clock_id, tp)
 
+static inline struct tm *
+rte_localtime_r(const time_t *timep, struct tm *result)
+{
+	if (localtime_s(result, timep) == 0)
+		return result;
+	else
+		return NULL;
+}
+#define localtime_r(timep, result) rte_localtime_r(timep, result)
+
 #endif /* _RTE_OS_SHIM_ */
lib/log/log.c +3 -4
index 255f757d94..7416c82b34 100644
@@ -14,13 +14,12 @@
 
 #include <rte_log.h>
 #include <rte_per_lcore.h>
-
-#include "log_internal.h"
-
 #ifdef RTE_EXEC_ENV_WINDOWS
-#define strdup _strdup
+#include <rte_os_shim.h>
 #endif
 
+#include "log_internal.h"
+
 struct rte_log_dynamic_type {
 	const char *name;
 	uint32_t loglevel;
Signature · 1 line
2.45.2
#405 lore raw

PATCH v28 4/13 eal: make eal_log_level_parse common

In reply to Stephen Hemminger

The code to parse for log-level option should be same on all OS variants.

---
 lib/eal/common/eal_common_options.c | 40 +++++++++++++++++++++++++++
 lib/eal/common/eal_options.h        |  1 +
 lib/eal/freebsd/eal.c               | 42 -----------------------------
 lib/eal/linux/eal.c                 | 39 ---------------------------
 lib/eal/windows/eal.c               | 35 ------------------------
 5 files changed, 41 insertions(+), 116 deletions(-)
lib/eal/common/eal_common_options.c +40 -0
index f1a5e329a5..eb079a65a9 100644
@@ -1640,6 +1640,46 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
 	return -1;
 }
 
+/* Parse the all arguments looking for log related ones */
+int
+eal_log_level_parse(int argc, char * const argv[])
+{
+	struct internal_config *internal_conf = eal_get_internal_configuration();
+	int option_index, opt;
+	const int old_optind = optind;
+	const int old_optopt = optopt;
+	const int old_opterr = opterr;
+	char *old_optarg = optarg;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	const int old_optreset = optreset;
+	optreset = 1;
+#endif
+
+	optind = 1;
+	opterr = 0;
+
+	while ((opt = getopt_long(argc, argv, eal_short_options,
+				  eal_long_options, &option_index)) != EOF) {
+
+		switch (opt) {
+		case OPT_LOG_LEVEL_NUM:
+			if (eal_parse_common_option(opt, optarg, internal_conf) < 0)
+				return -1;
+			break;
+		}
+	}
+
+	/* restore getopt lib */
+	optind = old_optind;
+	optopt = old_optopt;
+	optarg = old_optarg;
+	opterr = old_opterr;
+#ifdef RTE_EXEC_ENV_FREEBSD
+	optreset = old_optreset;
+#endif
+	return 0;
+}
+
 int
 eal_parse_common_option(int opt, const char *optarg,
 			struct internal_config *conf)
lib/eal/common/eal_options.h +1 -0
index 3cc9cb6412..f3f2e104f6 100644
@@ -96,6 +96,7 @@ enum {
 extern const char eal_short_options[];
 extern const struct option eal_long_options[];
 
+int eal_log_level_parse(int argc, char * const argv[]);
 int eal_parse_common_option(int opt, const char *argv,
 			    struct internal_config *conf);
 int eal_option_device_parse(void);
lib/eal/freebsd/eal.c +0 -42

48 lines not on this page · raw message

lib/eal/linux/eal.c +0 -39
index 54577b7718..40d750ed0d 100644
@@ -546,45 +546,6 @@ eal_parse_vfio_vf_token(const char *vf_token)
 	return -1;
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	const int old_optind = optind;
-	const int old_optopt = optopt;
-	char * const old_optarg = optarg;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-	optind = 1;
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-				  eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg, internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	/* restore getopt lib */
-	optind = old_optind;
-	optopt = old_optopt;
-	optarg = old_optarg;
-}
-
 static int
 eal_parse_huge_worker_stack(const char *arg)
 {
lib/eal/windows/eal.c +0 -35
index 28b78a95a6..a77e590a72 100644
@@ -96,41 +96,6 @@ eal_usage(const char *prgname)
 	}
 }
 
-/* Parse the arguments for --log-level only */
-static void
-eal_log_level_parse(int argc, char **argv)
-{
-	int opt;
-	char **argvopt;
-	int option_index;
-	struct internal_config *internal_conf =
-		eal_get_internal_configuration();
-
-	argvopt = argv;
-
-	eal_reset_internal_config(internal_conf);
-
-	while ((opt = getopt_long(argc, argvopt, eal_short_options,
-		eal_long_options, &option_index)) != EOF) {
-
-		int ret;
-
-		/* getopt is not happy, stop right now */
-		if (opt == '?')
-			break;
-
-		ret = (opt == OPT_LOG_LEVEL_NUM) ?
-			eal_parse_common_option(opt, optarg,
-				internal_conf) : 0;
-
-		/* common parser is not happy */
-		if (ret < 0)
-			break;
-	}
-
-	optind = 0; /* reset getopt lib */
-}
-
 /* Parse the argument given in the command line of the application */
 static int
 eal_parse_args(int argc, char **argv)
Signature · 1 line
2.45.2
#406 lore raw

PATCH v28 5/13 eal: do not duplicate rte_init_alert() messages

In reply to Stephen Hemminger

The message already goes through logging, and does not need to be printed on stderr. Message level should be ALERT to match function name.

---
 lib/eal/freebsd/eal.c | 3 +--
 lib/eal/linux/eal.c   | 3 +--
 lib/eal/windows/eal.c | 1 -
 3 files changed, 2 insertions(+), 5 deletions(-)
lib/eal/freebsd/eal.c +1 -2
index d3b40e81d8..7b974608e4 100644
@@ -529,8 +529,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /* Launch threads, called at application init(). */
lib/eal/linux/eal.c +1 -2
index 40d750ed0d..c53a051405 100644
@@ -830,8 +830,7 @@ rte_eal_iopl_init(void)
 
 static void rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
-	EAL_LOG(ERR, "%s", msg);
+	EAL_LOG(ALERT, "%s", msg);
 }
 
 /*
lib/eal/windows/eal.c +0 -1
index a77e590a72..93f099a968 100644
@@ -181,7 +181,6 @@ sync_func(void *arg __rte_unused)
 static void
 rte_eal_init_alert(const char *msg)
 {
-	fprintf(stderr, "EAL: FATAL: %s\n", msg);
 	EAL_LOG(ERR, "%s", msg);
 }
 
Signature · 1 line
2.45.2
#407 lore raw

PATCH v28 6/13 eal: change rte_exit() output to match rte_log()

In reply to Stephen Hemminger

The rte_exit() output format confuses the timestamp and coloring options. Change it to use be a single line with proper prefix.

Before:

[     0.006481] EAL: Error - exiting with code: 1
  Cause: [     0.006489] Cannot init EAL: Permission denied

After:

[     0.006238] EAL: Error - exiting with code: 1
[     0.006250] EAL: Cannot init EAL: Permission denied
---
 lib/eal/common/eal_common_debug.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
lib/eal/common/eal_common_debug.c +2 -4
index 3e77995896..bcfcd6df6f 100644
@@ -36,15 +36,13 @@ rte_exit(int exit_code, const char *format, ...)
 	va_list ap;
 
 	if (exit_code != 0)
-		RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n"
-				"  Cause: ", exit_code);
+		EAL_LOG(CRIT, "Error - exiting with code: %d", exit_code);
 
 	va_start(ap, format);
 	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
 	va_end(ap);
 
 	if (rte_eal_cleanup() != 0 && rte_errno != EALREADY)
-		EAL_LOG(CRIT,
-			"EAL could not release all resources");
+		EAL_LOG(CRIT, "EAL could not release all resources");
 	exit(exit_code);
 }
Signature · 1 line
2.45.2
#408 lore raw

PATCH v28 7/13 log: rework syslog handling

In reply to Stephen Hemminger

Refactor how syslog is handled, make it common to Linux and FreeBSD The syslog facility property is better handled in lib/log rather than in eal. This also add syslog support to FreeBSD.

Log to syslog only if option is specified.
If no --syslog is given then use console only.

---
 app/test/test_eal_flags.c                     |  16 +--
 .../freebsd_gsg/freebsd_eal_parameters.rst    |  27 +++++
 .../prog_guide/env_abstraction_layer.rst      |   6 +-
 doc/guides/prog_guide/log_lib.rst             |   5 +-
 lib/eal/common/eal_common_options.c           |  57 ++--------
 lib/eal/common/eal_internal_cfg.h             |   1 -
 lib/eal/freebsd/eal.c                         |   5 +-
 lib/eal/linux/eal.c                           |  12 +--
 lib/eal/windows/eal.c                         |   6 +-
 lib/log/log.c                                 |  45 ++++----
 lib/log/log_freebsd.c                         |  12 ---
 lib/log/log_internal.h                        |  11 +-
 lib/log/log_linux.c                           |  61 -----------
 lib/log/log_private.h                         |  25 +++++
 lib/log/log_syslog.c                          | 100 ++++++++++++++++++
 lib/log/log_windows.c                         |  18 ----
 lib/log/meson.build                           |   6 +-
 lib/log/version.map                           |   2 +-
 18 files changed, 211 insertions(+), 204 deletions(-)
 delete mode 100644 lib/log/log_freebsd.c
 delete mode 100644 lib/log/log_linux.c
 create mode 100644 lib/log/log_private.h
 create mode 100644 lib/log/log_syslog.c
 delete mode 100644 lib/log/log_windows.c
app/test/test_eal_flags.c +8 -8
index 71d8dba731..9fcf0d56e6 100644
@@ -985,12 +985,12 @@ test_misc_flags(void)
 	/* With -v */
 	const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
 	/* With valid --syslog */
-	const char *argv3[] = {prgname, prefix, mp_flag,
-			"--syslog", "syslog"};
-	/* With empty --syslog (should fail) */
+	const char *argv3[] = {prgname, prefix, mp_flag, "--syslog=user"};
+	/* With empty --syslog (now defaults) */
 	const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
 	/* 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};
@@ -1080,15 +1080,15 @@ test_misc_flags(void)
 #endif
 
 	if (launch_proc(argv3) != 0) {
-		printf("Error - process did not run ok with --syslog flag\n");
+		printf("Error - process did not run ok with --syslog=user flag\n");
 		goto fail;
 	}
-	if (launch_proc(argv4) == 0) {
-		printf("Error - process run ok with empty --syslog flag\n");
+	if (launch_proc(argv4) != 0) {
+		printf("Error - process did not run ok with --syslog flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv5) == 0) {
-		printf("Error - process run ok with invalid --syslog flag\n");
+		printf("Error - process run ok with --syslog=invalid flag\n");
 		goto fail;
 	}
 	if (launch_proc(argv7) != 0) {
doc/guides/freebsd_gsg/freebsd_eal_parameters.rst +27 -0
index fba467a2ce..9270d9fa3b 100644
@@ -18,3 +18,30 @@ FreeBSD-specific EAL parameters
 -------------------------------
 
 There are currently no FreeBSD-specific EAL command-line parameters available.
+
+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
doc/guides/prog_guide/env_abstraction_layer.rst +3 -3
index b9fac1839d..9bafa30a0e 100644
@@ -851,9 +851,9 @@ Signal Safety
   Other functions are not signal safe because they use one or more
   library routines that are not themselves signal safe.
   For example, calling ``rte_panic()`` is not safe in a signal handler
-  because it uses ``rte_log()`` and ``rte_log()`` calls the
-  ``syslog()`` library function which is in the list of
-  signal safe functions in
+  because it uses ``rte_log()`` and ``rte_log()`` may call ``vfprintf()`` or
+  ``syslog()`` library functions which are not in the list of
+  signal safe functions
   `Signal-Safety manual page <https://man7.org/linux/man-pages/man7/signal-safety.7.html>`_.
 
   The set of functions that are expected to be async-signal-safe in DPDK
doc/guides/prog_guide/log_lib.rst +2 -3
index ff9d1b54a2..c87830ac00 100644
@@ -5,9 +5,7 @@ Log Library
 ===========
 
 The DPDK Log library provides the logging functionality for other DPDK libraries and drivers.
-By default, in a Linux application, logs are sent to syslog and also to the console.
-On FreeBSD and Windows applications, logs are sent only to the console.
-However, the log function can be overridden by the user to use a different logging mechanism.
+The messages can be sent to one or more sources controlled by the EAL command line options.
 
 Log Levels
 ----------
@@ -59,6 +57,7 @@ For example::
 
 Within an application, the same result can be got using the ``rte_log_set_level_pattern()`` or ``rte_log_set_level_regex()`` APIs.
 
+
 Using Logging APIs to Generate Log Messages
 -------------------------------------------
 
lib/eal/common/eal_common_options.c +6 -51

99 lines not on this page · raw message

lib/eal/common/eal_internal_cfg.h +0 -1
index 167ec501fa..f53ab8b4aa 100644
@@ -84,7 +84,6 @@ struct internal_config {
 	/**< true if storing all pages within single files (per-page-size,
 	 * per-node) non-legacy mode only.
 	 */
-	volatile int syslog_facility;	  /**< facility passed to openlog() */
 	/** default interrupt mode for VFIO */
 	volatile enum rte_intr_mode vfio_intr_mode;
 	/** the shared VF token for VFIO-PCI bound PF and VFs devices */
lib/eal/freebsd/eal.c +2 -3
index 7b974608e4..a609d40ee0 100644
@@ -11,7 +11,6 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <pthread.h>
-#include <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
 #include <stddef.h>
@@ -392,8 +391,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_LOG_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
lib/eal/linux/eal.c +3 -9
index c53a051405..0c44d0b6e3 100644
@@ -610,8 +610,8 @@ eal_parse_args(int argc, char **argv)
 			goto out;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -1103,13 +1103,7 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	if (eal_log_init(program_invocation_short_name,
-			 internal_conf->syslog_facility) < 0) {
-		rte_eal_init_alert("Cannot init logging.");
-		rte_errno = ENOMEM;
-		rte_atomic_store_explicit(&run_once, 0, rte_memory_order_relaxed);
-		return -1;
-	}
+	eal_log_init(program_invocation_short_name);
 
 #ifdef VFIO_PRESENT
 	if (rte_vfio_enable("vfio")) {
lib/eal/windows/eal.c +3 -3
index 93f099a968..cd8420a82c 100644
@@ -120,8 +120,8 @@ eal_parse_args(int argc, char **argv)
 			return -1;
 		}
 
-		/* eal_log_level_parse() already handled this option */
-		if (opt == OPT_LOG_LEVEL_NUM)
+		/* eal_log_level_parse() already handled these options */
+		if (opt == OPT_LOG_LEVEL_NUM || opt == OPT_SYSLOG_NUM)
 			continue;
 
 		ret = eal_parse_common_option(opt, optarg, internal_conf);
@@ -249,7 +249,7 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL, 0);
+	eal_log_init(NULL);
 
 	eal_log_level_parse(argc, argv);
 
lib/log/log.c +22 -23

96 lines not on this page · raw message

lib/log/log_freebsd.c deleted +0 -12
deleted file mode 100644
index 698d3c5423..0000000000
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Intel Corporation
- */
-
-#include <rte_common.h>
-#include "log_internal.h"
-
-int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
-{
-	return 0;
-}
lib/log/log_internal.h +4 -7
index 451629f1c1..3c46328e7b 100644
@@ -14,13 +14,7 @@
  * Initialize the default log stream.
  */
 __rte_internal
-int eal_log_init(const char *id, int facility);
-
-/*
- * Determine where log data is written when no call to rte_openlog_stream.
- */
-__rte_internal
-void eal_log_set_default(FILE *default_log);
+void eal_log_init(const char *id);
 
 /*
  * Save a log option for later.
@@ -30,6 +24,9 @@ int eal_log_save_regexp(const char *regexp, uint32_t level);
 __rte_internal
 int eal_log_save_pattern(const char *pattern, uint32_t level);
 
+__rte_internal
+int eal_log_syslog(const char *name);
+
 /*
  * Convert log level to string.
  */
lib/log/log_linux.c deleted +0 -61

61 lines not on this page · raw message

lib/log/log_private.h new file +25 -0
new file mode 100644
index 0000000000..bf87b43f7e
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+
+#ifndef LOG_PRIVATE_H
+#define LOG_PRIVATE_H
+
+/* Defined in limits.h on Linux */
+#ifndef LINE_MAX
+#define LINE_MAX	2048 /* _POSIX2_LINE_MAX */
+#endif
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+static inline bool log_syslog_enabled(void)
+{
+	return false;
+}
+static inline FILE *log_syslog_open(const char *id __rte_unused)
+{
+	return NULL;
+}
+#else
+bool log_syslog_enabled(void);
+FILE *log_syslog_open(const char *id);
+#endif
+
+#endif /* LOG_PRIVATE_H */
lib/log/log_syslog.c new file +100 -0

100 lines not on this page · raw message

lib/log/log_windows.c deleted +0 -18
deleted file mode 100644
index a6a0889550..0000000000
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017-2018 Intel Corporation
- */
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include "log_internal.h"
-
-/* set the log to default function, called during eal init process. */
-int
-eal_log_init(__rte_unused const char *id, __rte_unused int facility)
-{
-	rte_openlog_stream(stderr);
-
-	eal_log_set_default(stderr);
-
-	return 0;
-}
lib/log/meson.build +5 -1
index 0d4319b36f..160cf34f50 100644
@@ -4,6 +4,10 @@
 includes += global_inc
 sources = files(
         'log.c',
-        'log_' + exec_env + '.c',
 )
+
+if not is_windows
+    sources += files('log_syslog.c')
+endif
+
 headers = files('rte_log.h')
lib/log/version.map +1 -1
index 19d7f9cdb6..1637fba3b9 100644
@@ -29,6 +29,6 @@ INTERNAL {
 	eal_log_level2str;
 	eal_log_save_pattern;
 	eal_log_save_regexp;
-	eal_log_set_default;
+	eal_log_syslog; # WINDOWS_NO_EXPORT
 	rte_eal_log_cleanup;
 };
Signature · 1 line
2.45.2
#409 lore raw

PATCH v28 8/13 eal: initialize log before everything else

In reply to Stephen Hemminger

In order for all log messages (including CPU mismatch) to come out through the logging library, it must be initialized as early in rte_eal_init() as possible on all platforms.

Where it was done before was likely historical based on the support of non-OS isolated CPU's which required a shared memory buffer; that support was dropped before DPDK was publicly released.

---
 lib/eal/freebsd/eal.c  | 13 ++++++++++---
 lib/eal/linux/eal.c    | 14 +++++++++-----
 lib/eal/windows/eal.c  |  8 ++++++--
 lib/log/log_internal.h |  6 ++++++
 4 files changed, 31 insertions(+), 10 deletions(-)
lib/eal/freebsd/eal.c +10 -3
index a609d40ee0..8631a20eae 100644
@@ -52,6 +52,7 @@
 #include "eal_options.h"
 #include "eal_memcfg.h"
 #include "eal_trace.h"
+#include "log_internal.h"
 
 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
 
@@ -546,6 +547,15 @@ rte_eal_init(int argc, char **argv)
 	bool has_phys_addr;
 	enum rte_iova_mode iova_mode;
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(getprogname());
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -572,9 +582,6 @@ rte_eal_init(int argc, char **argv)
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	if (rte_eal_cpu_init() < 0) {
 		rte_eal_init_alert("Cannot detect lcores.");
 		rte_errno = ENOTSUP;
lib/eal/linux/eal.c +9 -5
index 0c44d0b6e3..62d3d281c4 100644
@@ -926,6 +926,15 @@ rte_eal_init(int argc, char **argv)
 	struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 
+	/* setup log as early as possible */
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
+
+	eal_log_init(program_invocation_short_name);
+
 	/* checks if the machine is adequate */
 	if (!rte_cpu_is_supported()) {
 		rte_eal_init_alert("unsupported cpu type.");
@@ -949,9 +958,6 @@ rte_eal_init(int argc, char **argv)
 
 	eal_reset_internal_config(internal_conf);
 
-	/* set log level as early as possible */
-	eal_log_level_parse(argc, argv);
-
 	/* clone argv to report out later in telemetry */
 	eal_save_args(argc, argv);
 
@@ -1103,8 +1109,6 @@ rte_eal_init(int argc, char **argv)
 #endif
 	}
 
-	eal_log_init(program_invocation_short_name);
-
 #ifdef VFIO_PRESENT
 	if (rte_vfio_enable("vfio")) {
 		rte_eal_init_alert("Cannot init VFIO");
lib/eal/windows/eal.c +6 -2
index cd8420a82c..33f044d7cc 100644
@@ -249,9 +249,13 @@ rte_eal_init(int argc, char **argv)
 	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 	char thread_name[RTE_THREAD_NAME_SIZE];
 
-	eal_log_init(NULL);
+	if (eal_log_level_parse(argc, argv) < 0) {
+		rte_eal_init_alert("invalid log arguments.");
+		rte_errno = EINVAL;
+		return -1;
+	}
 
-	eal_log_level_parse(argc, argv);
+	eal_log_init(NULL);
 
 	if (eal_create_cpu_map() < 0) {
 		rte_eal_init_alert("Cannot discover CPU and NUMA.");
lib/log/log_internal.h +6 -0
index 3c46328e7b..d5fabd7ef7 100644
@@ -16,6 +16,12 @@
 __rte_internal
 void eal_log_init(const char *id);
 
+/*
+ * Determine where log data is written when no call to rte_openlog_stream.
+ */
+__rte_internal
+void eal_log_set_default(FILE *default_log);
+
 /*
  * Save a log option for later.
  */
Signature · 1 line
2.45.2