eal: add option to put timestamp on console output
PATCH v28 9/13 log: add hook for printing log messages
In reply to Stephen HemmingerThis 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
@@ -30,16 +30,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 {
@@ -76,6 +81,7 @@ int rte_openlog_stream(FILE *f) { rte_logs.file = f; + rte_logs.print_func = vfprintf;return 0 ; }
@@ -472,7 +478,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
PATCH v28 10/13 log: add timestamp option
In reply to Stephen HemmingerWhen 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 | 240 ++++++++++++++++++++++++++++ lib/log/meson.build | 1 + lib/log/version.map | 1 + 13 files changed, 341 insertions(+), 7 deletions(-) create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -514,6 +514,11 @@ eal_log_init(const char *id)if (logf)rte_openlog_stream (logf); +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
@@ -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>
@@ -45,4 +47,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
@@ -22,4 +22,10 @@ bool log_syslog_enabled(void);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 +240 -0
240 lines not on this page · raw message
lib/log/meson.build +1 -0
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_timestamp.c', ) if not is_windows
lib/log/version.map +1 -0
@@ -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
PATCH v28 11/13 log: add support for systemd journal
In reply to Stephen HemmingerIf 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 | 7 +- lib/log/log_internal.h | 3 + lib/log/log_journal.c | 154 +++++++++++++++++++++++++++++++++++++++++ lib/log/log_private.h | 14 ++++ lib/log/log_syslog.c | 9 +++ lib/log/meson.build | 4 ++ lib/log/version.map | 1 + 7 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 lib/log/log_journal.c
lib/log/log.c +4 -3
@@ -508,13 +508,14 @@ eal_log_init(const char *id) {FILE *logf =NULL ; -if (log_syslog_enabled ()) +if (log_journal_enabled ()) + logf =log_journal_open (id); +else if (log_syslog_enabled ()) logf =log_syslog_open (id);if (logf)rte_openlog_stream (logf); - -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
@@ -35,6 +35,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 +14 -0
@@ -22,6 +22,20 @@ 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 +static inline bool log_journal_enabled (void ) +{ +return false; +} +static inline FILE *log_journal_open(const char *id __rte_unused) +{ +return 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 +9 -0
@@ -18,6 +18,10 @@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;
lib/log/meson.build +4 -0
@@ -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
@@ -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
Re: [PATCH v28 11/13] log: add support for systemd journal
Can we have an option to disable journal auto-detection?
In my case I want to redirect the DPDK to our own tracing infrastructure and for that I use the fopencookie myself and redirect it to our own system. The journal will force it out and I'll need to ensure that the environment variable is not set, which is doable but I'd rather not need to mess with the environment and just set a flag in dpdk options to disable the journal.
Quoted 306 lines · 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:
Signed-off-by Stephen Hemminger <[email protected]>Acked-by Morten Brørup <[email protected]>Acked-by Bruce Richardson <[email protected]>--- lib/log/log.c | 7 +- lib/log/log_internal.h | 3 + lib/log/log_journal.c | 154 +++++++++++++++++++++++++++++++++++++++++ lib/log/log_private.h | 14 ++++ lib/log/log_syslog.c | 9 +++ lib/log/meson.build | 4 ++ lib/log/version.map | 1 + 7 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 lib/log/log_journal.clib/log/log.c +4
-3@@ -508,13 +508,14 @@ eal_log_init(const char *id) {FILE *logf =NULL ; -if (log_syslog_enabled ()) +if (log_journal_enabled ()) + logf =log_journal_open (id); +else if (log_syslog_enabled ()) logf =log_syslog_open (id);if (logf)rte_openlog_stream (logf); - -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@@ -35,6 +35,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 +23
-0@@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include <limits.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <unistd.h> + +#include <rte_common.h> +#include <rte_log.h> + +#include "log_internal.h" +#include "log_private.h" + +/* +* Send structured message using journal protocol +* See: https://url.avanan.click/v2/r01/___https://systemd.io/JOURNAL_NATIVE_PROTOCOL/___.YXAzOndla2E6YTpnOjc1MmU1YTVhODIzMWJiMTdkNTBhNzE4MDVhNDc2MTBhOjc6NTQxZDoyMWQ3NGFjZGMwYWE0M2RhZTM4OTc0ZmJjNGY1NzFkZTFlNTZmMTEwM2I3ZDNhN2U3ZDkxNzFmZjg4ODU3NGQxOnA6VDpO
+ *
+ * Useswritev()to ensure that whole log message is in one datagram
+ */lib/log/log_journal.c new file +58
-0+static int +journal_send (int fd,const char *buf,size_t len) +{ +struct iovec iov[4 ]; +unsigned int n =0 ; +int priority =rte_log_cur_msg_loglevel () -1 ; +char msg[] ="MESSAGE=" ; +char newline ='\n' ; +char pbuf[32 ];/* "PRIORITY=N\n" */ + + iov[n].iov_base = msg; + iov[n++].iov_len =strlen (msg); + + iov[n].iov_base = (char *)(uintptr_t )buf; + iov[n++].iov_len = len; + +/* if message doesn't end with newline, one will be applied. */ +if (buf[len -1 ] !='\n' ) { + iov[n].iov_base = &newline; + iov[n++].iov_len =1 ; + } + +/* priority value between 0 ("emerg") and 7 ("debug") */ + iov[n].iov_base = pbuf; + iov[n++].iov_len =snprintf (pbuf,sizeof (pbuf), +"PRIORITY=%d\n" , priority); +return writev (fd, iov, n); +} + + +/* wrapper for log stream to put messages into journal */ +static ssize_t +journal_log_write (void *c,const char *buf,size_t size) +{ +int fd = (uintptr_t )c; + +return journal_send (fd, buf, size); +} + +static int +journal_log_close (void *c) +{ +int fd = (uintptr_t )c; + +close (fd); +return 0 ; +} + +static cookie_io_functions_t journal_log_func = { + .write = journal_log_write, + .close = journal_log_close, +}; + +/* +* Check if stderr is going to system journal. +* This is the documented way to handle systemd journal +* +* See: lib/log/log_journal.c new file +38
-0+bool +log_journal_enabled (void ) +{ +char *jenv, *endp =NULL ; +struct stat st; +unsigned long dev, ino; + + jenv =getenv ("JOURNAL_STREAM" ); +if (jenv ==NULL ) +return false; + +if (fstat (STDERR_FILENO , &st) <0 ) +return false; + +/* systemd sets colon-separated list of device and inode number */ + dev =strtoul (jenv, &endp,10 ); +if (endp ==NULL || *endp !=':' ) +return false;/* missing colon */ + + ino =strtoul (endp +1 ,NULL ,10 ); + +return dev == st.st_dev && ino == st.st_ino; +} + +/* Connect to systemd's journal service */ +FILE *log_journal_open (const char *id) +{ +char syslog_id[PATH_MAX ]; +FILE *log_stream; +int len; +struct sockaddr_un sun = { + .sun_family =AF_UNIX , + .sun_path ="/run/systemd/journal/socket" , + }; +int jfd =-1 ; + + len = snprintf(syslog_id, sizeof(syslog_id), + "SYSLOG_IDENTIFIER=%s\nSYSLOG_PID=%u", id,
getpid());lib/log/log_journal.c new file +24
-0+ +/* Detect truncation of message and fallback to no journal */ +if (len >= (int )sizeof (syslog_id)) +return NULL ; + + jfd =socket (AF_UNIX ,SOCK_DGRAM ,0 ); +if (jfd <0 ) { +perror ("socket" ); + goto error; + } + +if (connect (jfd, (struct sockaddr *)&sun,sizeof (sun)) <0 ) { +perror ("connect" ); + goto error; + } + +/* Send identifier as first message */ +if (write (jfd, syslog_id, len) != len) { +perror ("write" ); + goto error; + } + +/* redirect other log messages to journal */ + log_stream = fopencookie((void *)(uintptr_t)jfd, "w",
journal_log_func);lib/log/log_journal.c new file +7
-0+if (log_stream !=NULL ) +return log_stream; + +error: +close (jfd); +return NULL ; +}lib/log/log_private.h +14
-0@@ -22,6 +22,20 @@ 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 +static inline bool log_journal_enabled (void ) +{ +return false; +} +static inline FILE *log_journal_open(const char *id __rte_unused) +{ +return 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 +9
-0@@ -18,6 +18,10 @@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;lib/log/meson.build +4
-0@@ -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
-1@@ -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; --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>
Re: [PATCH v28 11/13] log: add support for systemd journal
Quoted 8 lines · On Fri, 25 Oct 2024 18:33:40 +0300 Baruch Even <[email protected]> wrote:
Can we have an option to disable journal auto-detection?
In my case I want to redirect the DPDK to our own tracing infrastructure and for that I use the fopencookie myself and redirect it to our own system. The journal will force it out and I'll need to ensure that the environment variable is not set, which is doable but I'd rather not need to mess with the environment and just set a flag in dpdk options to disable the journal.
The detection works on stderr being associated with a specific device that is passed in by environment variable. Only systemd service is going to get this. If you wanted to override, either change the service file.
If you redirect the with rte_openlog_stream() that should already override the stderr. Stuff, probably need to add a check for that.
PATCH v28 12/13 log: colorize log output
In reply to Stephen HemmingerLike 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 | 214 ++++++++++++++++++++++++++++ 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, 306 insertions(+), 4 deletions(-) create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 +214 -0
214 lines not on this page · raw message
lib/log/log_internal.h +5 -0
@@ -56,5 +56,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
@@ -42,4 +42,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
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_color.c', 'log_timestamp.c', )
lib/log/version.map +1 -0
@@ -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
PATCH v28 13/13 doc: add release note about log library
In reply to Stephen HemmingerSignificant 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
@@ -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
v29 cover Logging subsystem enhancements
In reply to Stephen HemmingerImprovements 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.
v29 - address review feedback and change wording of release note
If a log stream is set with rte_open_log_stream() then none of the other stuff happens (syslog, journal, timestamp, or color)
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 | 20 ++ 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 | 83 ++++-- lib/log/log_color.c | 214 ++++++++++++++++ lib/log/log_freebsd.c | 12 - lib/log/log_internal.h | 22 +- lib/log/log_journal.c | 152 +++++++++++ lib/log/log_linux.c | 61 ----- lib/log/log_private.h | 53 ++++ lib/log/log_syslog.c | 108 ++++++++ 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, 1163 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
PATCH v29 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
@@ -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
PATCH v29 2/13 windows: make getopt functions have const properties
In reply to Stephen HemmingerHaving 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
@@ -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
@@ -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
PATCH v29 3/13 windows: update os shim
In reply to Stephen HemmingerWindows 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
@@ -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
@@ -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
PATCH v29 4/13 eal: make eal_log_level_parse common
In reply to Stephen HemmingerThe 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v29 5/13 eal: do not duplicate rte_init_alert() messages
In reply to Stephen HemmingerThe 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
@@ -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
@@ -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
@@ -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
PATCH v29 6/13 eal: change rte_exit() output to match rte_log()
In reply to Stephen HemmingerThe 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
@@ -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
PATCH v29 7/13 log: rework syslog handling
In reply to Stephen HemmingerRefactor 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 | 44 ++++----- 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 | 99 +++++++++++++++++++ lib/log/log_windows.c | 18 ---- lib/log/meson.build | 6 +- lib/log/version.map | 2 +- 18 files changed, 209 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 +21 -23
94 lines not on this page · raw message
lib/log/log_freebsd.c deleted +0 -12
@@ -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
@@ -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
@@ -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 +99 -0
99 lines not on this page · raw message
lib/log/log_windows.c deleted +0 -18
@@ -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
@@ -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
@@ -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
PATCH v29 8/13 eal: initialize log before everything else
In reply to Stephen HemmingerIn 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v29 9/13 log: add hook for printing log messages
In reply to Stephen HemmingerThis 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
@@ -29,16 +29,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 {
@@ -75,6 +80,7 @@ int rte_openlog_stream(FILE *f) { rte_logs.file = f; + rte_logs.print_func = vfprintf;return 0 ; }
@@ -471,7 +477,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
PATCH v29 10/13 log: add timestamp option
In reply to Stephen HemmingerWhen 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 | 240 ++++++++++++++++++++++++++++ lib/log/meson.build | 1 + lib/log/version.map | 1 + 13 files changed, 341 insertions(+), 7 deletions(-) create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -513,6 +513,11 @@ eal_log_init(const char *id)if (logf)rte_openlog_stream (logf); +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
@@ -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>
@@ -45,4 +47,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
@@ -22,4 +22,10 @@ bool log_syslog_enabled(void);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 +240 -0
240 lines not on this page · raw message
lib/log/meson.build +1 -0
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_timestamp.c', ) if not is_windows
lib/log/version.map +1 -0
@@ -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
PATCH v29 11/13 log: add support for systemd journal
In reply to Stephen HemmingerIf 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 | 32 +++++---- lib/log/log_internal.h | 3 + lib/log/log_journal.c | 152 +++++++++++++++++++++++++++++++++++++++++ lib/log/log_private.h | 14 ++++ lib/log/log_syslog.c | 9 +++ lib/log/meson.build | 4 ++ lib/log/version.map | 1 + 7 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 lib/log/log_journal.c
lib/log/log.c +20 -12
@@ -505,18 +505,26 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)void eal_log_init (const char *id) { -FILE *logf =NULL ; - -if (log_syslog_enabled ()) - logf =log_syslog_open (id); - -if (logf) -rte_openlog_stream (logf); - -if (log_timestamp_enabled ()) - rte_logs.print_func = log_print_with_timestamp; -else - rte_logs.print_func = vfprintf; +/* If user has already set a log stream, then use it. */ +if (rte_logs.file ==NULL ) { +FILE *logf =NULL ; + +/* if stderr is assocated with systemd environment */ +if (log_journal_enabled ()) + logf =log_journal_open (id); +/* If --syslog option was passed */ +else if (log_syslog_enabled ()) + logf =log_syslog_open (id); + +/* if either syslog or journal is used, then no special handling */ +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; + }#if RTE_LOG_DP_LEVEL >=RTE_LOG_DEBUG RTE_LOG(NOTICE, EAL,
lib/log/log_internal.h +3 -0
@@ -35,6 +35,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 +152 -0
152 lines not on this page · raw message
lib/log/log_private.h +14 -0
@@ -22,6 +22,20 @@ 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 +static inline bool log_journal_enabled (void ) +{ +return false; +} +static inline FILE *log_journal_open(const char *id __rte_unused) +{ +return 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 +9 -0
@@ -17,6 +17,10 @@static int log_facility; +/* +* Usable list of facilities +* Skip kern, mark, and security +*/ static const struct { const char *name; int value;
@@ -47,6 +51,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;
lib/log/meson.build +4 -0
@@ -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
@@ -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
PATCH v29 12/13 log: colorize log output
In reply to Stephen HemmingerLike 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 | 21 ++- lib/log/log_color.c | 214 ++++++++++++++++++++++++++++ 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, 307 insertions(+), 4 deletions(-) create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
@@ -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=never 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
@@ -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
@@ -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
@@ -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 +17 -4
@@ -12,6 +12,7 @@#include <regex.h> #include <fnmatch.h> #include <sys/queue.h> +#include <unistd.h> #include <rte_common.h> #include <rte_log.h>
@@ -520,10 +521,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
lib/log/log_color.c new file +214 -0
214 lines not on this page · raw message
lib/log/log_internal.h +5 -0
@@ -56,5 +56,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
@@ -42,4 +42,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
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_color.c', 'log_timestamp.c', )
lib/log/version.map +1 -0
@@ -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
PATCH v29 13/13 doc: add release note about log library
In reply to Stephen HemmingerSignificant enough to warrant a release note.
--- doc/guides/rel_notes/release_24_11.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
doc/guides/rel_notes/release_24_11.rst +20 -0
@@ -349,6 +349,26 @@ 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. + + * If the application is a systemd service and the log output is being + sent to standard error then DPDK will switch to journal native protocol. + This allows the more data such as severity to be sent. + + * The syslog option has changed. By default, messages are no longer sent + to syslog unless the *--syslog* option is specified. + Syslog is also now now supported on FreeBSD (but not on Windows). + + * 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
v30 cover Log library enhancements
In reply to Stephen HemmingerImprovements 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.
v30 - add isatty() to windows os shim
fix wording in release note etc.
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 | 60 ++++- doc/guides/rel_notes/release_24_11.rst | 20 ++ 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 | 12 + lib/log/log.c | 83 ++++-- lib/log/log_color.c | 214 ++++++++++++++++ lib/log/log_freebsd.c | 12 - lib/log/log_internal.h | 22 +- lib/log/log_journal.c | 152 +++++++++++ lib/log/log_linux.c | 61 ----- lib/log/log_private.h | 53 ++++ lib/log/log_syslog.c | 108 ++++++++ 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, 1168 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
PATCH v30 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
@@ -187,6 +187,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
PATCH v30 2/13 windows: make getopt functions have const properties
In reply to Stephen HemmingerHaving 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
@@ -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
@@ -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
PATCH v30 3/13 windows: update os shim
In reply to Stephen HemmingerWindows 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.
Add fileno() and isatty() to the wrapper.
--- lib/eal/windows/include/rte_os_shim.h | 12 ++++++++++++ lib/log/log.c | 7 +++---- 2 files changed, 15 insertions(+), 4 deletions(-)
lib/eal/windows/include/rte_os_shim.h +12 -0
@@ -30,6 +30,8 @@#define write (fd, buf, n) _write(fd, buf, n)#define close (fd) _close(fd)#define unlink (path) _unlink(path) +#define fileno (f) _fileno(f) +#define isatty (fd) _isatty(fd)#define IPVERSION 4
@@ -110,4 +112,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
@@ -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
PATCH v30 4/13 eal: make eal_log_level_parse common
In reply to Stephen HemmingerThe 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v30 5/13 eal: do not duplicate rte_init_alert() messages
In reply to Stephen HemmingerThe 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
@@ -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
@@ -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
@@ -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
PATCH v30 6/13 eal: change rte_exit() output to match rte_log()
In reply to Stephen HemmingerThe 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
@@ -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
PATCH v30 7/13 log: rework syslog handling
In reply to Stephen HemmingerRefactor 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 only standard error.
--- 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 | 7 +- 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 | 44 ++++----- 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 | 99 +++++++++++++++++++ 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
@@ -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
@@ -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
@@ -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 +4 -3
@@ -5,9 +5,10 @@ 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. +By default, logs are sent only to standard error output of the process. +The syslog EAL option can be used to redirect to the stystem logger +on Linux and FreeBSD. +In addition, the log can be redirected to a different stdio file stream. Log Levels ----------
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
@@ -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
@@ -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
@@ -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
@@ -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 +21 -23
94 lines not on this page · raw message
lib/log/log_freebsd.c deleted +0 -12
@@ -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
@@ -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
@@ -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 +99 -0
99 lines not on this page · raw message
lib/log/log_windows.c deleted +0 -18
@@ -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
@@ -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
@@ -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
PATCH v30 8/13 eal: initialize log before everything else
In reply to Stephen HemmingerIn 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v30 9/13 log: add hook for printing log messages
In reply to Stephen HemmingerThis 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
@@ -29,16 +29,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 {
@@ -75,6 +80,7 @@ int rte_openlog_stream(FILE *f) { rte_logs.file = f; + rte_logs.print_func = vfprintf;return 0 ; }
@@ -471,7 +477,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
PATCH v30 10/13 log: add timestamp option
In reply to Stephen HemmingerWhen 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 | 29 ++++ 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 | 240 ++++++++++++++++++++++++++++ lib/log/meson.build | 1 + lib/log/version.map | 1 + 13 files changed, 341 insertions(+), 6 deletions(-) create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +26 -0
@@ -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 -0
@@ -111,3 +111,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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -513,6 +513,11 @@ eal_log_init(const char *id)if (logf)rte_openlog_stream (logf); +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
@@ -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>
@@ -45,4 +47,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
@@ -22,4 +22,10 @@ bool log_syslog_enabled(void);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 +240 -0
240 lines not on this page · raw message
lib/log/meson.build +1 -0
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_timestamp.c', ) if not is_windows
lib/log/version.map +1 -0
@@ -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
PATCH v30 11/13 log: add support for systemd journal
In reply to Stephen HemmingerIf 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 | 32 +++++---- lib/log/log_internal.h | 3 + lib/log/log_journal.c | 152 +++++++++++++++++++++++++++++++++++++++++ lib/log/log_private.h | 14 ++++ lib/log/log_syslog.c | 9 +++ lib/log/meson.build | 4 ++ lib/log/version.map | 1 + 7 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 lib/log/log_journal.c
lib/log/log.c +20 -12
@@ -505,18 +505,26 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)void eal_log_init (const char *id) { -FILE *logf =NULL ; - -if (log_syslog_enabled ()) - logf =log_syslog_open (id); - -if (logf) -rte_openlog_stream (logf); - -if (log_timestamp_enabled ()) - rte_logs.print_func = log_print_with_timestamp; -else - rte_logs.print_func = vfprintf; +/* If user has already set a log stream, then use it. */ +if (rte_logs.file ==NULL ) { +FILE *logf =NULL ; + +/* if stderr is assocated with systemd environment */ +if (log_journal_enabled ()) + logf =log_journal_open (id); +/* If --syslog option was passed */ +else if (log_syslog_enabled ()) + logf =log_syslog_open (id); + +/* if either syslog or journal is used, then no special handling */ +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; + }#if RTE_LOG_DP_LEVEL >=RTE_LOG_DEBUG RTE_LOG(NOTICE, EAL,
lib/log/log_internal.h +3 -0
@@ -35,6 +35,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 +152 -0
152 lines not on this page · raw message
lib/log/log_private.h +14 -0
@@ -22,6 +22,20 @@ 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 +static inline bool log_journal_enabled (void ) +{ +return false; +} +static inline FILE *log_journal_open(const char *id __rte_unused) +{ +return 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 +9 -0
@@ -17,6 +17,10 @@static int log_facility; +/* +* Usable list of facilities +* Skip kern, mark, and security +*/ static const struct { const char *name; int value;
@@ -47,6 +51,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;
lib/log/meson.build +4 -0
@@ -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
@@ -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
PATCH v30 12/13 log: colorize log output
In reply to Stephen HemmingerLike 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 | 21 ++- lib/log/log_color.c | 214 ++++++++++++++++++++++++++++ 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, 307 insertions(+), 4 deletions(-) create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
@@ -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=never 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
@@ -60,6 +60,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 -------------------------------------------
@@ -140,3 +141,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
@@ -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
@@ -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 +17 -4
@@ -12,6 +12,7 @@#include <regex.h> #include <fnmatch.h> #include <sys/queue.h> +#include <unistd.h> #include <rte_common.h> #include <rte_log.h>
@@ -520,10 +521,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
lib/log/log_color.c new file +214 -0
214 lines not on this page · raw message
lib/log/log_internal.h +5 -0
@@ -56,5 +56,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
@@ -42,4 +42,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
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_color.c', 'log_timestamp.c', )
lib/log/version.map +1 -0
@@ -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
PATCH v30 13/13 doc: add release note about log library
In reply to Stephen HemmingerSignificant enough to warrant a release note.
--- doc/guides/rel_notes/release_24_11.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
doc/guides/rel_notes/release_24_11.rst +20 -0
@@ -353,6 +353,26 @@ 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. + + * If the application is a systemd service and the log output is being + sent to standard error then DPDK will switch to journal native protocol. + This allows the more data such as severity to be sent. + + * The syslog option has changed. By default, messages are no longer sent + to syslog unless the *--syslog* option is specified. + Syslog is also supported on FreeBSD (but not on Windows). + + * 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
v31 cover Log library enhancements
In reply to Stephen HemmingerImprovements 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 Stephen as maintainer for log because by now have added more than previous authors.
Resending for CI after some small/cosmetic changes:
Changes since v30:
- added a little helper that identifies log options (this fixed a little bug with the color option being parsed twice) and
renamed eal_log_level_parse() as eal_parse_log_options(),
- adjusted log level to ALERT for EAL error on Windows,
- split RN updates in relevant patches and fixed style,
- fixed --syslog usage string,
- split and squashed Windows shim update in relevant patches,
- fixed typos,
- cleaned duplicate inclusion of headers,
- moved syslog facility code update in relevant patch,
- removed dead reference to eal_log_set_default,
Signature · 58 lines
David Marchand David Marchand (1): eal: introduce log options parser Stephen Hemminger (11): eal/windows: align getopt to FreeBSD eal: factorize parser for log level eal: do not log init failure twice eal: improve exit output log log: rework syslog handling eal: initialize log before everything else log: add hook for printing log messages log: add timestamp option log: support systemd journal log: colorize log output maintainers: update for log library MAINTAINERS | 1 + app/test/test_eal_flags.c | 64 ++++- .../freebsd_gsg/freebsd_eal_parameters.rst | 27 ++ .../prog_guide/env_abstraction_layer.rst | 6 +- doc/guides/prog_guide/log_lib.rst | 58 ++++- doc/guides/rel_notes/release_24_11.rst | 16 ++ lib/eal/common/eal_common_debug.c | 6 +- lib/eal/common/eal_common_options.c | 132 ++++++---- lib/eal/common/eal_internal_cfg.h | 1 - lib/eal/common/eal_options.h | 6 + lib/eal/freebsd/eal.c | 63 +---- lib/eal/linux/eal.c | 66 +---- lib/eal/windows/eal.c | 51 +--- lib/eal/windows/getopt.c | 23 +- lib/eal/windows/include/getopt.h | 8 +- lib/eal/windows/include/rte_os_shim.h | 12 + lib/log/log.c | 82 ++++-- lib/log/log_color.c | 214 ++++++++++++++++ lib/log/log_freebsd.c | 12 - lib/log/log_internal.h | 28 +- lib/log/log_journal.c | 153 +++++++++++ lib/log/log_linux.c | 61 ----- lib/log/log_private.h | 57 +++++ lib/log/log_syslog.c | 108 ++++++++ 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, 1171 insertions(+), 359 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.47.0
PATCH v31 1/12 eal/windows: align getopt to FreeBSD
From: Stephen Hemminger <[email protected]>
Having different prototypes on different platforms can lead to lots of unnecessary workarounds. It 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
@@ -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
@@ -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.47.0
PATCH v31 2/12 eal: factorize parser for log level
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -1640,6 +1640,46 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)return -1 ; } +/* Parse the arguments for --log-level only */ +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
@@ -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
@@ -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
@@ -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.47.0
PATCH v31 3/12 eal: introduce log options parser
In reply to David MarchandRename existing log level option parser and add a little helper tracking all options related to logs.
This will make it easier to add more log options in the next commits.
--- lib/eal/common/eal_common_options.c | 26 ++++++++++++++++++-------- lib/eal/common/eal_options.h | 3 ++- lib/eal/freebsd/eal.c | 8 ++++---- lib/eal/linux/eal.c | 8 ++++---- lib/eal/windows/eal.c | 7 ++++--- 5 files changed, 32 insertions(+), 20 deletions(-)
lib/eal/common/eal_common_options.c +18 -8
@@ -1640,9 +1640,20 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)return -1 ; } -/* Parse the arguments for --log-level only */ +bool +eal_option_is_log (int opt) +{ +switch (opt) { +case OPT_LOG_LEVEL_NUM : +return true; +default : +return false; + } +} + +/* Parse all arguments looking for log related ones */ int -eal_log_level_parse (int argc,char *const argv[]) +eal_parse_log_options (int argc,char *const argv[]) {struct internal_config *internal_conf =eal_get_internal_configuration ();int option_index, opt;
@@ -1661,12 +1672,11 @@ eal_log_level_parse(int argc, char * const argv[])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 ; - } +if (!eal_option_is_log (opt)) +continue ; + +if (eal_parse_common_option (opt, optarg, internal_conf) <0 ) +return -1 ; }/* restore getopt lib */
lib/eal/common/eal_options.h +2 -1
@@ -96,7 +96,8 @@ enum {extern const char eal_short_options[];extern const struct option eal_long_options[]; -int eal_log_level_parse (int argc,char *const argv[]); +bool eal_option_is_log (int opt); +int eal_parse_log_options (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 +4 -4
@@ -392,8 +392,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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -574,8 +574,8 @@ 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); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);if (rte_eal_cpu_init () <0 ) {rte_eal_init_alert ("Cannot detect lcores." );
lib/eal/linux/eal.c +4 -4
@@ -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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -950,8 +950,8 @@ 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); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);/* clone argv to report out later in telemetry */ eal_save_args (argc, argv);
lib/eal/windows/eal.c +4 -3
@@ -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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -252,7 +252,8 @@ rte_eal_init(int argc, char **argv)eal_log_init (NULL ,0 ); -eal_log_level_parse (argc, argv); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);if (eal_create_cpu_map () <0 ) {rte_eal_init_alert ("Cannot discover CPU and NUMA." );
Signature · 1 line
2.47.0
PATCH v31 4/12 eal: do not log init failure twice
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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 | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-)
lib/eal/freebsd/eal.c +1 -2
@@ -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
@@ -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 +1 -2
@@ -181,8 +181,7 @@ 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); +EAL_LOG (ALERT ,"%s" , msg); }/* Stubs to enable EAL trace point compilation
Signature · 1 line
2.47.0
PATCH v31 5/12 eal: improve exit output log
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -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.47.0
PATCH v31 6/12 log: rework syslog handling
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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 adds syslog support to FreeBSD.
Log to syslog only if option is specified.
If no --syslog is given then use only standard error.
--- 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 | 6 +- doc/guides/rel_notes/release_24_11.rst | 6 + lib/eal/common/eal_common_options.c | 57 +-------- lib/eal/common/eal_internal_cfg.h | 1 - lib/eal/freebsd/eal.c | 1 - lib/eal/linux/eal.c | 8 +- lib/eal/windows/eal.c | 2 +- lib/log/log.c | 43 ++++--- lib/log/log_freebsd.c | 12 -- lib/log/log_internal.h | 11 +- lib/log/log_linux.c | 61 ---------- lib/log/log_private.h | 27 +++++ lib/log/log_syslog.c | 108 ++++++++++++++++++ lib/log/log_windows.c | 18 --- lib/log/meson.build | 6 +- lib/log/version.map | 2 +- 19 files changed, 220 insertions(+), 198 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
@@ -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
@@ -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
@@ -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 +3 -3
@@ -5,9 +5,9 @@ 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. +By default, logs are sent only to standard error output of the process. +The syslog EAL option can be used to redirect to the stystem logger on Linux and FreeBSD. +In addition, the log can be redirected to a different stdio file stream. Log Levels ----------
doc/guides/rel_notes/release_24_11.rst +6 -0
@@ -100,6 +100,12 @@ New Features (and vice versa); freeing the same pointer twice in the same routine; freeing an object that was not created by allocation; etc. +* **Updated logging library** + + * The syslog option has changed. + By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. + Syslog is also supported on FreeBSD (but not on Windows). + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
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
@@ -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 +0 -1
@@ -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>
lib/eal/linux/eal.c +1 -7
@@ -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 +1 -1
@@ -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 );/* parse log options as early as possible */ eal_parse_log_options (argc, argv);
lib/log/log.c +20 -23
90 lines not on this page · raw message
lib/log/log_freebsd.c deleted +0 -12
@@ -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
@@ -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 +27 -0
@@ -0,0 +1,27 @@ +/* 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 +108 -0
108 lines not on this page · raw message
lib/log/log_windows.c deleted +0 -18
@@ -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
@@ -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
@@ -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.47.0
PATCH v31 7/12 eal: initialize log before everything else
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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.
--- doc/guides/rel_notes/release_24_11.rst | 2 ++ lib/eal/freebsd/eal.c | 13 ++++++++++--- lib/eal/linux/eal.c | 14 +++++++++----- lib/eal/windows/eal.c | 10 +++++++--- 4 files changed, 28 insertions(+), 11 deletions(-)
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -102,6 +102,8 @@ New Features * **Updated logging library** + * The log subsystem is initialized earlier in startup so all messages go through the library. + * The syslog option has changed. By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows).
lib/eal/freebsd/eal.c +10 -3
@@ -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_parse_log_options (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); -/* parse log options as early as possible */ -eal_parse_log_options (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
@@ -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_parse_log_options (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); -/* parse log options as early as possible */ -eal_parse_log_options (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 +7 -3
@@ -249,10 +249,14 @@ 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 ); +/* setup log as early as possible */ +if (eal_parse_log_options (argc, argv) <0 ) { +rte_eal_init_alert ("invalid log arguments." ); + rte_errno =EINVAL ; +return -1 ; + } -/* parse log options as early as possible */ -eal_parse_log_options (argc, argv); +eal_log_init (NULL );if (eal_create_cpu_map () <0 ) {rte_eal_init_alert ("Cannot discover CPU and NUMA." );
Signature · 1 line
2.47.0
PATCH v31 8/12 log: add hook for printing log messages
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -29,16 +29,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 {
@@ -75,6 +80,7 @@ int rte_openlog_stream(FILE *f) { rte_logs.file = f; + rte_logs.print_func = vfprintf;return 0 ; }
@@ -471,7 +477,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.47.0
PATCH v31 9/12 log: add timestamp option
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
Note: Windows does not have localtime_r but it does have a similar function that can be used instead. Add it to rte_os_shim.h.
--- app/test/test_eal_flags.c | 24 +++ doc/guides/prog_guide/log_lib.rst | 28 +++ doc/guides/rel_notes/release_24_11.rst | 2 + lib/eal/common/eal_common_options.c | 14 +- lib/eal/common/eal_options.h | 2 + lib/eal/windows/include/rte_os_shim.h | 10 ++ lib/log/log.c | 13 +- lib/log/log_internal.h | 9 + lib/log/log_private.h | 6 + lib/log/log_timestamp.c | 240 +++++++++++++++++++++++++ lib/log/meson.build | 1 + lib/log/version.map | 1 + 12 files changed, 344 insertions(+), 6 deletions(-) create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +24 -0
@@ -1055,6 +1055,18 @@ 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 +1174,18 @@ 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 +28 -0
@@ -110,3 +110,31 @@ 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 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.
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -108,6 +108,8 @@ New Features By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows). + * Log messages can be timestamped with ``--log-timestamp`` option. + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
lib/eal/common/eal_common_options.c +12 -2
@@ -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 },
@@ -1599,6 +1600,7 @@ eal_option_is_log(int opt) {switch (opt) {case OPT_LOG_LEVEL_NUM : +case OPT_LOG_TIMESTAMP_NUM :case OPT_SYSLOG_NUM :return true;default :
@@ -1850,7 +1852,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 --"
@@ -1858,7 +1860,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 : {
@@ -2225,6 +2234,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
@@ -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/windows/include/rte_os_shim.h +10 -0
@@ -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 +9 -4
@@ -17,13 +17,13 @@#include <rte_log.h> #include <rte_per_lcore.h> -#include "log_internal.h" -#include "log_private.h" -#ifdef RTE_EXEC_ENV_WINDOWS -#define strdup _strdup +#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;
@@ -513,6 +513,11 @@ eal_log_init(const char *id)if (logf)rte_openlog_stream (logf); +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
@@ -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
@@ -24,4 +24,10 @@ bool log_syslog_enabled(void);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 +240 -0
240 lines not on this page · raw message
lib/log/meson.build +1 -0
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_timestamp.c', ) if not is_windows
lib/log/version.map +1 -0
@@ -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.47.0
PATCH v31 10/12 log: support systemd journal
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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/rel_notes/release_24_11.rst | 4 + lib/log/log.c | 31 +++-- lib/log/log_internal.h | 3 + lib/log/log_journal.c | 153 +++++++++++++++++++++++++ lib/log/log_private.h | 16 +++ lib/log/meson.build | 4 + lib/log/version.map | 1 + 7 files changed, 200 insertions(+), 12 deletions(-) create mode 100644 lib/log/log_journal.c
doc/guides/rel_notes/release_24_11.rst +4 -0
@@ -104,6 +104,10 @@ New Features * The log subsystem is initialized earlier in startup so all messages go through the library. + * If the application is a systemd service and the log output is being sent to standard error + then DPDK will switch to journal native protocol. + This allows the more data such as severity to be sent. + * The syslog option has changed. By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows).
lib/log/log.c +19 -12
@@ -505,18 +505,25 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)void eal_log_init (const char *id) { -FILE *logf =NULL ; - -if (log_syslog_enabled ()) - logf =log_syslog_open (id); - -if (logf) -rte_openlog_stream (logf); - -if (log_timestamp_enabled ()) - rte_logs.print_func = log_print_with_timestamp; -else - rte_logs.print_func = vfprintf; +/* If user has already set a log stream, then use it. */ +if (rte_logs.file ==NULL ) { +FILE *logf =NULL ; + +/* if stderr is associated with systemd environment */ +if (log_journal_enabled ()) + logf =log_journal_open (id); +/* If --syslog option was passed */ +else if (log_syslog_enabled ()) + logf =log_syslog_open (id); + +/* if either syslog or journal is used, then no special handling */ +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; + }#if RTE_LOG_DP_LEVEL >=RTE_LOG_DEBUG RTE_LOG(NOTICE, EAL,
lib/log/log_internal.h +3 -0
@@ -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 +153 -0
153 lines not on this page · raw message
lib/log/log_private.h +16 -0
@@ -24,6 +24,22 @@ 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 +static inline bool +log_journal_enabled (void ) +{ +return false; +} +static inline FILE * +log_journal_open(const char *id __rte_unused) +{ +return NULL ; +} +#endif /* !RTE_EXEC_ENV_LINUX */ +bool log_timestamp_enabled (void );ssize_t log_timestamp (char *tsbuf,size_t tsbuflen);
lib/log/meson.build +4 -0
@@ -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
@@ -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.47.0
PATCH v31 11/12 log: colorize log output
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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.
Note: add fileno() and isatty() to the Windows wrapper.
--- app/test/test_eal_flags.c | 24 +++ doc/guides/prog_guide/log_lib.rst | 24 +++ doc/guides/rel_notes/release_24_11.rst | 2 + lib/eal/common/eal_common_options.c | 11 ++ lib/eal/common/eal_options.h | 2 + lib/eal/windows/include/rte_os_shim.h | 2 + lib/log/log.c | 23 ++- lib/log/log_color.c | 214 +++++++++++++++++++++++++ lib/log/log_internal.h | 5 + lib/log/log_private.h | 8 + lib/log/meson.build | 1 + lib/log/version.map | 1 + 12 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
@@ -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 */ if (launch_proc (argv0) ==0 ) {
@@ -1186,6 +1198,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=never 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);rmdir (hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +24 -0
@@ -59,6 +59,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 -------------------------------------------
@@ -138,3 +139,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.
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -114,6 +114,8 @@ New Features * Log messages can be timestamped with ``--log-timestamp`` option. + * Log messages can be colorized with the ``--log-color`` option. + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
lib/eal/common/eal_common_options.c +11 -0
@@ -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 },
@@ -1599,6 +1600,7 @@ bool eal_option_is_log(int opt) {switch (opt) { +case OPT_LOG_COLOR_NUM :case OPT_LOG_LEVEL_NUM :case OPT_LOG_TIMESTAMP_NUM :case OPT_SYSLOG_NUM :
@@ -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 ) {
@@ -2235,6 +2245,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
@@ -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/eal/windows/include/rte_os_shim.h +2 -0
@@ -30,6 +30,8 @@#define write (fd, buf, n) _write(fd, buf, n)#define close (fd) _close(fd)#define unlink (path) _unlink(path) +#define fileno (f) _fileno(f) +#define isatty (fd) _isatty(fd)#define IPVERSION 4
lib/log/log.c +18 -5
@@ -12,6 +12,7 @@#include <regex.h> #include <fnmatch.h> #include <sys/queue.h> +#include <unistd.h> #include <rte_common.h> #include <rte_log.h>
@@ -517,12 +518,24 @@ eal_log_init(const char *id) logf =log_syslog_open (id);/* if either syslog or journal is used, then no special handling */ -if (logf) +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
lib/log/log_color.c new file +214 -0
214 lines not on this page · raw message
lib/log/log_internal.h +5 -0
@@ -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
@@ -46,4 +46,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
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_color.c', 'log_timestamp.c', )
lib/log/version.map +1 -0
@@ -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.47.0
PATCH v31 12/12 maintainers: update for log library
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
"You touch it you own it".
Add myself as maintainer for log library.
--- MAINTAINERS | 1 + 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
@@ -193,6 +193,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.47.0
Re: [PATCH v31 00/12] Log library enhancements
In reply to David MarchandQuoted 39 lines · David Marchand
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 Stephen as maintainer for log because by now have added more than previous authors.
Resending for CI after some small/cosmetic changes:
Quoted 12 lines
Changes since v30:
- added a little helper that identifies log options (this fixed a little bug with the color option being parsed twice) and
renamedeal_log_level_parse()aseal_parse_log_options(),
- adjusted log level to ALERT for EAL error on Windows,
- split RN updates in relevant patches and fixed style,
- fixed --syslog usage string,
- split and squashed Windows shim update in relevant patches,
- fixed typos,
- cleaned duplicate inclusion of headers,
- moved syslog facility code update in relevant patch,
- removed dead reference toeal_log_set_default,
The escape character \e is refused with MSVC.
This had been reported as a warning starting v26 iiuc:
==== 20 line log output for Windows Server 2022 (dpdk_msvc_compile): ====
...
[ 3 5 / 9 6 ] C o m p i l i n g C o b j e c t l i b / l i b
r t e _ l o g . a . p / l o g _ l o g _ c o l o r . c . o b j
F A I L E D : l i b / l i b r t e _ l o g . a . p / l o g _ l o g
_ c o l o r . c . o b j
" c l " " - I l i b \ l i b r t e _ l o g . a . p " " - I l i b
" " - I . . \ l i b " " - I . " " - I . . " " - I c o n f i g
" " - I . . \ c o n f i g " " - I l i b \ e a l \ i n c l u d e "
" - I . . \ l i b \ e a l \ i n c l u d e " " - I l i b \ e a l \ w
i n d o w s \ i n c l u d e " " - I . . \ l i b \ e a l \ w i n d o
w s \ i n c l u d e " " - I l i b \ e a l \ x 8 6 \ i n c l u d e "
" - I . . \ l i b \ e a l \ x 8 6 \ i n c l u d e " " - I l i b \ l
o g " " - I . . \ l i b \ l o g " " - I C : \ P r o g r a m F i
l e s \ M e l l a n o x \ M L N X _ W i n O F 2 _ D e v X _ S D K \ i
n c " " / M D " " / n o l o g o " " / s h o w I n c l u d e s "
" / W 3 " " / W X " " / s t d : c 1 1 " " / O 2 " " / G w "
" / w d 4 2 4 4 " " / w d 4 2 6 7 " " / w d 4 1 4 6 " " / e x p
e r i m e n t a l : c 1 1 a t o m i c s " " / d 1 e x p e r i m e n
t a l : t y p e o f " " / e x p e r i m e n t a l : s t a t e m e n
t E x p r e s
s i o n s " " / F I " " r t e _ c o n f i g . h " " - D _ G N
U _ S O U R C E " " - D _ W I N 3 2 _ W I N N T = 0 x 0 A 0 0 " "
- D A L L O W _ E X P E R I M E N T A L _ A P I " " - D A L L O W _
I N T E R N A L _ A P I " " - D R T E _ L O G _ D E F A U L T _ L O
G T Y P E = l i b . l o g " " / F d l i b \ l i b r t e _ l o g . a
. p \ l o g _ l o g _ c o l o r . c . p d b " / F o l i b / l i b r
t e _ l o g . a . p / l o g _ l o g _ c o l o r . c . o b j " / c "
. . / l i b / l o g / l o g _ c o l o r . c
. . / l i b / l o g / l o g _ c o l o r . c ( 8 6 ) : e r r o r
C 2 2 2 0 : t h e f o l l o w i n g w a r n i n g i s t r e
a t e d a s a n e r r o r
. . / l i b / l o g / l o g _ c o l o r . c ( 8 6 ) : w a r n i n
g C 4 1 2 9 : ' e ' : u n r e c o g n i z e d c h a r a c t e r e s c a p e s e q u e n c e . . / l i b / l o g / l o g _ c o l o r . c ( 8 6 ) : w a r n i n g C 4 1 2 9 : ' e ' : u n r e c o g n i z e d c h a r a c t e r e s c a p e s e q u e n c e . . / l i b / l o g / l o g _ c o l o r . c ( 8 8 ) : w a r n i n g C 4 1 2 9 : ' e ' : u n r e c o g n i z e d c h a r a c t e r e s c a p e s e q u e n c e
Respinning the series with \033 (that was used until v25) and we should be good.
Signature · 1 line
David Marchand
v31 cover Log library enhancements
In reply to Stephen HemmingerImprovements 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 Stephen as maintainer for log because by now have added more than previous authors.
Resending for CI:
Changes since v31:
- rebased,
- fixed build with MSVC: escape character was restored to \033 (used until v25) instead of \e,
Changes since v30:
- added a little helper that identifies log options (this fixed a little bug with the color option being parsed twice) and
renamed eal_log_level_parse() as eal_parse_log_options(),
- adjusted log level to ALERT for EAL error on Windows,
- split RN updates in relevant patches and fixed style,
- fixed --syslog usage string,
- split and squashed Windows shim update in relevant patches,
- fixed typos,
- cleaned duplicate inclusion of headers,
- moved syslog facility code update in relevant patch,
- removed dead reference to eal_log_set_default,
Signature · 58 lines
David Marchand David Marchand (1): eal: introduce log options parser Stephen Hemminger (11): eal/windows: align getopt to FreeBSD eal: factorize parser for log level eal: do not log init failure twice eal: improve exit output log log: rework syslog handling eal: initialize log before everything else log: add hook for printing log messages log: add timestamp option log: support systemd journal log: colorize log output maintainers: update for log library MAINTAINERS | 1 + app/test/test_eal_flags.c | 64 ++++- .../freebsd_gsg/freebsd_eal_parameters.rst | 27 ++ .../prog_guide/env_abstraction_layer.rst | 6 +- doc/guides/prog_guide/log_lib.rst | 58 ++++- doc/guides/rel_notes/release_24_11.rst | 16 ++ lib/eal/common/eal_common_debug.c | 6 +- lib/eal/common/eal_common_options.c | 132 ++++++---- lib/eal/common/eal_internal_cfg.h | 1 - lib/eal/common/eal_options.h | 6 + lib/eal/freebsd/eal.c | 63 +---- lib/eal/linux/eal.c | 66 +---- lib/eal/windows/eal.c | 51 +--- lib/eal/windows/getopt.c | 23 +- lib/eal/windows/include/getopt.h | 8 +- lib/eal/windows/include/rte_os_shim.h | 12 + lib/log/log.c | 82 ++++-- lib/log/log_color.c | 214 ++++++++++++++++ lib/log/log_freebsd.c | 12 - lib/log/log_internal.h | 28 +- lib/log/log_journal.c | 153 +++++++++++ lib/log/log_linux.c | 61 ----- lib/log/log_private.h | 57 +++++ lib/log/log_syslog.c | 108 ++++++++ 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, 1171 insertions(+), 359 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.47.0
PATCH v32 1/12 eal/windows: align getopt to FreeBSD
From: Stephen Hemminger <[email protected]>
Having different prototypes on different platforms can lead to lots of unnecessary workarounds. It 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
@@ -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
@@ -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.47.0
PATCH v32 2/12 eal: factorize parser for log level
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -1640,6 +1640,46 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)return -1 ; } +/* Parse the arguments for --log-level only */ +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
@@ -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
@@ -547,45 +547,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
@@ -97,41 +97,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.47.0
PATCH v32 3/12 eal: introduce log options parser
In reply to David MarchandRename existing log level option parser and add a little helper tracking all options related to logs.
This will make it easier to add more log options in the next commits.
--- lib/eal/common/eal_common_options.c | 26 ++++++++++++++++++-------- lib/eal/common/eal_options.h | 3 ++- lib/eal/freebsd/eal.c | 8 ++++---- lib/eal/linux/eal.c | 8 ++++---- lib/eal/windows/eal.c | 7 ++++--- 5 files changed, 32 insertions(+), 20 deletions(-)
lib/eal/common/eal_common_options.c +18 -8
@@ -1640,9 +1640,20 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)return -1 ; } -/* Parse the arguments for --log-level only */ +bool +eal_option_is_log (int opt) +{ +switch (opt) { +case OPT_LOG_LEVEL_NUM : +return true; +default : +return false; + } +} + +/* Parse all arguments looking for log related ones */ int -eal_log_level_parse (int argc,char *const argv[]) +eal_parse_log_options (int argc,char *const argv[]) {struct internal_config *internal_conf =eal_get_internal_configuration ();int option_index, opt;
@@ -1661,12 +1672,11 @@ eal_log_level_parse(int argc, char * const argv[])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 ; - } +if (!eal_option_is_log (opt)) +continue ; + +if (eal_parse_common_option (opt, optarg, internal_conf) <0 ) +return -1 ; }/* restore getopt lib */
lib/eal/common/eal_options.h +2 -1
@@ -96,7 +96,8 @@ enum {extern const char eal_short_options[];extern const struct option eal_long_options[]; -int eal_log_level_parse (int argc,char *const argv[]); +bool eal_option_is_log (int opt); +int eal_parse_log_options (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 +4 -4
@@ -393,8 +393,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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -575,8 +575,8 @@ 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); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);if (rte_eal_cpu_init () <0 ) {rte_eal_init_alert ("Cannot detect lcores." );
lib/eal/linux/eal.c +4 -4
@@ -611,8 +611,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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -951,8 +951,8 @@ 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); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);/* clone argv to report out later in telemetry */ eal_save_args (argc, argv);
lib/eal/windows/eal.c +4 -3
@@ -121,8 +121,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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -254,7 +254,8 @@ rte_eal_init(int argc, char **argv)eal_log_init (NULL ,0 ); -eal_log_level_parse (argc, argv); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);if (eal_create_cpu_map () <0 ) {rte_eal_init_alert ("Cannot discover CPU and NUMA." );
Signature · 1 line
2.47.0
PATCH v32 4/12 eal: do not log init failure twice
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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 | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-)
lib/eal/freebsd/eal.c +1 -2
@@ -530,8 +530,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
@@ -831,8 +831,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 +1 -2
@@ -182,8 +182,7 @@ 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); +EAL_LOG (ALERT ,"%s" , msg); }/* Stubs to enable EAL trace point compilation
Signature · 1 line
2.47.0
PATCH v32 5/12 eal: improve exit output log
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -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.47.0
PATCH v32 6/12 log: rework syslog handling
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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 adds syslog support to FreeBSD.
Log to syslog only if option is specified.
If no --syslog is given then use only standard error.
--- 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 | 6 +- doc/guides/rel_notes/release_24_11.rst | 6 + lib/eal/common/eal_common_options.c | 57 +-------- lib/eal/common/eal_internal_cfg.h | 1 - lib/eal/freebsd/eal.c | 1 - lib/eal/linux/eal.c | 8 +- lib/eal/windows/eal.c | 2 +- lib/log/log.c | 43 ++++--- lib/log/log_freebsd.c | 12 -- lib/log/log_internal.h | 11 +- lib/log/log_linux.c | 61 ---------- lib/log/log_private.h | 27 +++++ lib/log/log_syslog.c | 108 ++++++++++++++++++ lib/log/log_windows.c | 18 --- lib/log/meson.build | 6 +- lib/log/version.map | 2 +- 19 files changed, 220 insertions(+), 198 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
@@ -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
@@ -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
@@ -884,9 +884,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 +3 -3
@@ -5,9 +5,9 @@ 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. +By default, logs are sent only to standard error output of the process. +The syslog EAL option can be used to redirect to the stystem logger on Linux and FreeBSD. +In addition, the log can be redirected to a different stdio file stream. Log Levels ----------
doc/guides/rel_notes/release_24_11.rst +6 -0
@@ -114,6 +114,12 @@ New Features (and vice versa); freeing the same pointer twice in the same routine; freeing an object that was not created by allocation; etc. +* **Updated logging library** + + * The syslog option has changed. + By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. + Syslog is also supported on FreeBSD (but not on Windows). + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
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
@@ -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 +0 -1
@@ -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>
lib/eal/linux/eal.c +1 -7
@@ -1104,13 +1104,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 +1 -1
@@ -251,7 +251,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 );/* parse log options as early as possible */ eal_parse_log_options (argc, argv);
lib/log/log.c +20 -23
90 lines not on this page · raw message
lib/log/log_freebsd.c deleted +0 -12
@@ -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
@@ -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 +27 -0
@@ -0,0 +1,27 @@ +/* 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 +108 -0
108 lines not on this page · raw message
lib/log/log_windows.c deleted +0 -18
@@ -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
@@ -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
@@ -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.47.0
PATCH v32 7/12 eal: initialize log before everything else
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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.
--- doc/guides/rel_notes/release_24_11.rst | 2 ++ lib/eal/freebsd/eal.c | 13 ++++++++++--- lib/eal/linux/eal.c | 14 +++++++++----- lib/eal/windows/eal.c | 10 +++++++--- 4 files changed, 28 insertions(+), 11 deletions(-)
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -116,6 +116,8 @@ New Features * **Updated logging library** + * The log subsystem is initialized earlier in startup so all messages go through the library. + * The syslog option has changed. By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows).
lib/eal/freebsd/eal.c +10 -3
@@ -53,6 +53,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)
@@ -547,6 +548,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_parse_log_options (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." );
@@ -573,9 +583,6 @@ rte_eal_init(int argc, char **argv)/* clone argv to report out later in telemetry */ eal_save_args (argc, argv); -/* parse log options as early as possible */ -eal_parse_log_options (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
@@ -927,6 +927,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_parse_log_options (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." );
@@ -950,9 +959,6 @@ rte_eal_init(int argc, char **argv)eal_reset_internal_config (internal_conf); -/* parse log options as early as possible */ -eal_parse_log_options (argc, argv); -/* clone argv to report out later in telemetry */ eal_save_args (argc, argv);
@@ -1104,8 +1110,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 +7 -3
@@ -251,10 +251,14 @@ 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 ); +/* setup log as early as possible */ +if (eal_parse_log_options (argc, argv) <0 ) { +rte_eal_init_alert ("invalid log arguments." ); + rte_errno =EINVAL ; +return -1 ; + } -/* parse log options as early as possible */ -eal_parse_log_options (argc, argv); +eal_log_init (NULL );if (eal_create_cpu_map () <0 ) {rte_eal_init_alert ("Cannot discover CPU and NUMA." );
Signature · 1 line
2.47.0
PATCH v32 8/12 log: add hook for printing log messages
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -29,16 +29,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 {
@@ -75,6 +80,7 @@ int rte_openlog_stream(FILE *f) { rte_logs.file = f; + rte_logs.print_func = vfprintf;return 0 ; }
@@ -471,7 +477,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.47.0
PATCH v32 9/12 log: add timestamp option
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
Note: Windows does not have localtime_r but it does have a similar function that can be used instead. Add it to rte_os_shim.h.
--- app/test/test_eal_flags.c | 24 +++ doc/guides/prog_guide/log_lib.rst | 28 +++ doc/guides/rel_notes/release_24_11.rst | 2 + lib/eal/common/eal_common_options.c | 14 +- lib/eal/common/eal_options.h | 2 + lib/eal/windows/include/rte_os_shim.h | 10 ++ lib/log/log.c | 13 +- lib/log/log_internal.h | 9 + lib/log/log_private.h | 6 + lib/log/log_timestamp.c | 240 +++++++++++++++++++++++++ lib/log/meson.build | 1 + lib/log/version.map | 1 + 12 files changed, 344 insertions(+), 6 deletions(-) create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +24 -0
@@ -1055,6 +1055,18 @@ 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 +1174,18 @@ 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 +28 -0
@@ -110,3 +110,31 @@ 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 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.
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -122,6 +122,8 @@ New Features By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows). + * Log messages can be timestamped with ``--log-timestamp`` option. + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
lib/eal/common/eal_common_options.c +12 -2
@@ -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 },
@@ -1599,6 +1600,7 @@ eal_option_is_log(int opt) {switch (opt) {case OPT_LOG_LEVEL_NUM : +case OPT_LOG_TIMESTAMP_NUM :case OPT_SYSLOG_NUM :return true;default :
@@ -1850,7 +1852,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 --"
@@ -1858,7 +1860,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 : {
@@ -2225,6 +2234,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
@@ -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/windows/include/rte_os_shim.h +10 -0
@@ -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 +9 -4
@@ -17,13 +17,13 @@#include <rte_log.h> #include <rte_per_lcore.h> -#include "log_internal.h" -#include "log_private.h" -#ifdef RTE_EXEC_ENV_WINDOWS -#define strdup _strdup +#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;
@@ -513,6 +513,11 @@ eal_log_init(const char *id)if (logf)rte_openlog_stream (logf); +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
@@ -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
@@ -24,4 +24,10 @@ bool log_syslog_enabled(void);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 +240 -0
240 lines not on this page · raw message
lib/log/meson.build +1 -0
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_timestamp.c', ) if not is_windows
lib/log/version.map +1 -0
@@ -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.47.0
PATCH v32 10/12 log: support systemd journal
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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/rel_notes/release_24_11.rst | 4 + lib/log/log.c | 31 +++-- lib/log/log_internal.h | 3 + lib/log/log_journal.c | 153 +++++++++++++++++++++++++ lib/log/log_private.h | 16 +++ lib/log/meson.build | 4 + lib/log/version.map | 1 + 7 files changed, 200 insertions(+), 12 deletions(-) create mode 100644 lib/log/log_journal.c
doc/guides/rel_notes/release_24_11.rst +4 -0
@@ -118,6 +118,10 @@ New Features * The log subsystem is initialized earlier in startup so all messages go through the library. + * If the application is a systemd service and the log output is being sent to standard error + then DPDK will switch to journal native protocol. + This allows the more data such as severity to be sent. + * The syslog option has changed. By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows).
lib/log/log.c +19 -12
@@ -505,18 +505,25 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)void eal_log_init (const char *id) { -FILE *logf =NULL ; - -if (log_syslog_enabled ()) - logf =log_syslog_open (id); - -if (logf) -rte_openlog_stream (logf); - -if (log_timestamp_enabled ()) - rte_logs.print_func = log_print_with_timestamp; -else - rte_logs.print_func = vfprintf; +/* If user has already set a log stream, then use it. */ +if (rte_logs.file ==NULL ) { +FILE *logf =NULL ; + +/* if stderr is associated with systemd environment */ +if (log_journal_enabled ()) + logf =log_journal_open (id); +/* If --syslog option was passed */ +else if (log_syslog_enabled ()) + logf =log_syslog_open (id); + +/* if either syslog or journal is used, then no special handling */ +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; + }#if RTE_LOG_DP_LEVEL >=RTE_LOG_DEBUG RTE_LOG(NOTICE, EAL,
lib/log/log_internal.h +3 -0
@@ -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 +153 -0
153 lines not on this page · raw message
lib/log/log_private.h +16 -0
@@ -24,6 +24,22 @@ 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 +static inline bool +log_journal_enabled (void ) +{ +return false; +} +static inline FILE * +log_journal_open(const char *id __rte_unused) +{ +return NULL ; +} +#endif /* !RTE_EXEC_ENV_LINUX */ +bool log_timestamp_enabled (void );ssize_t log_timestamp (char *tsbuf,size_t tsbuflen);
lib/log/meson.build +4 -0
@@ -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
@@ -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.47.0
PATCH v32 11/12 log: colorize log output
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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.
Note: add fileno() and isatty() to the Windows wrapper.
--- app/test/test_eal_flags.c | 24 +++ doc/guides/prog_guide/log_lib.rst | 24 +++ doc/guides/rel_notes/release_24_11.rst | 2 + lib/eal/common/eal_common_options.c | 11 ++ lib/eal/common/eal_options.h | 2 + lib/eal/windows/include/rte_os_shim.h | 2 + lib/log/log.c | 23 ++- lib/log/log_color.c | 214 +++++++++++++++++++++++++ lib/log/log_internal.h | 5 + lib/log/log_private.h | 8 + lib/log/meson.build | 1 + lib/log/version.map | 1 + 12 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
@@ -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 */ if (launch_proc (argv0) ==0 ) {
@@ -1186,6 +1198,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=never 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);rmdir (hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +24 -0
@@ -59,6 +59,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 -------------------------------------------
@@ -138,3 +139,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.
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -128,6 +128,8 @@ New Features * Log messages can be timestamped with ``--log-timestamp`` option. + * Log messages can be colorized with the ``--log-color`` option. + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
lib/eal/common/eal_common_options.c +11 -0
@@ -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 },
@@ -1599,6 +1600,7 @@ bool eal_option_is_log(int opt) {switch (opt) { +case OPT_LOG_COLOR_NUM :case OPT_LOG_LEVEL_NUM :case OPT_LOG_TIMESTAMP_NUM :case OPT_SYSLOG_NUM :
@@ -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 ) {
@@ -2235,6 +2245,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
@@ -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/eal/windows/include/rte_os_shim.h +2 -0
@@ -30,6 +30,8 @@#define write (fd, buf, n) _write(fd, buf, n)#define close (fd) _close(fd)#define unlink (path) _unlink(path) +#define fileno (f) _fileno(f) +#define isatty (fd) _isatty(fd)#define IPVERSION 4
lib/log/log.c +18 -5
@@ -12,6 +12,7 @@#include <regex.h> #include <fnmatch.h> #include <sys/queue.h> +#include <unistd.h> #include <rte_common.h> #include <rte_log.h>
@@ -517,12 +518,24 @@ eal_log_init(const char *id) logf =log_syslog_open (id);/* if either syslog or journal is used, then no special handling */ -if (logf) +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
lib/log/log_color.c new file +214 -0
214 lines not on this page · raw message
lib/log/log_internal.h +5 -0
@@ -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
@@ -46,4 +46,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
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_color.c', 'log_timestamp.c', )
lib/log/version.map +1 -0
@@ -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.47.0
PATCH v32 12/12 maintainers: update for log library
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
"You touch it you own it".
Add myself as maintainer for log library.
--- MAINTAINERS | 1 + 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
@@ -193,6 +193,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.47.0
v32 cover Log library enhancements
In reply to Stephen HemmingerImprovements 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 Stephen as maintainer for log because by now have added more than previous authors.
Resending for CI:
Changes since v31:
- rebased,
- fixed build with MSVC: escape character was restored to \033 (used until v25) instead of \e,
Changes since v30:
- added a little helper that identifies log options (this fixed a little bug with the color option being parsed twice) and
renamed eal_log_level_parse() as eal_parse_log_options(),
- adjusted log level to ALERT for EAL error on Windows,
- split RN updates in relevant patches and fixed style,
- fixed --syslog usage string,
- split and squashed Windows shim update in relevant patches,
- fixed typos,
- cleaned duplicate inclusion of headers,
- moved syslog facility code update in relevant patch,
- removed dead reference to eal_log_set_default,
Signature · 58 lines
David Marchand David Marchand (1): eal: introduce log options parser Stephen Hemminger (11): eal/windows: align getopt to FreeBSD eal: factorize parser for log level eal: do not log init failure twice eal: improve exit output log log: rework syslog handling eal: initialize log before everything else log: add hook for printing log messages log: add timestamp option log: support systemd journal log: colorize log output maintainers: update for log library MAINTAINERS | 1 + app/test/test_eal_flags.c | 64 ++++- .../freebsd_gsg/freebsd_eal_parameters.rst | 27 ++ .../prog_guide/env_abstraction_layer.rst | 6 +- doc/guides/prog_guide/log_lib.rst | 58 ++++- doc/guides/rel_notes/release_24_11.rst | 16 ++ lib/eal/common/eal_common_debug.c | 6 +- lib/eal/common/eal_common_options.c | 132 ++++++---- lib/eal/common/eal_internal_cfg.h | 1 - lib/eal/common/eal_options.h | 6 + lib/eal/freebsd/eal.c | 63 +---- lib/eal/linux/eal.c | 66 +---- lib/eal/windows/eal.c | 51 +--- lib/eal/windows/getopt.c | 23 +- lib/eal/windows/include/getopt.h | 8 +- lib/eal/windows/include/rte_os_shim.h | 12 + lib/log/log.c | 82 ++++-- lib/log/log_color.c | 214 ++++++++++++++++ lib/log/log_freebsd.c | 12 - lib/log/log_internal.h | 28 +- lib/log/log_journal.c | 153 +++++++++++ lib/log/log_linux.c | 61 ----- lib/log/log_private.h | 57 +++++ lib/log/log_syslog.c | 108 ++++++++ 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, 1171 insertions(+), 359 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.47.0
PATCH v32 1/12 eal/windows: align getopt to FreeBSD
From: Stephen Hemminger <[email protected]>
Having different prototypes on different platforms can lead to lots of unnecessary workarounds. It 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
@@ -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
@@ -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.47.0
PATCH v32 2/12 eal: factorize parser for log level
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -1640,6 +1640,46 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)return -1 ; } +/* Parse the arguments for --log-level only */ +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
@@ -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
@@ -547,45 +547,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
@@ -97,41 +97,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.47.0
PATCH v32 3/12 eal: introduce log options parser
In reply to David MarchandRename existing log level option parser and add a little helper tracking all options related to logs.
This will make it easier to add more log options in the next commits.
--- lib/eal/common/eal_common_options.c | 26 ++++++++++++++++++-------- lib/eal/common/eal_options.h | 3 ++- lib/eal/freebsd/eal.c | 8 ++++---- lib/eal/linux/eal.c | 8 ++++---- lib/eal/windows/eal.c | 7 ++++--- 5 files changed, 32 insertions(+), 20 deletions(-)
lib/eal/common/eal_common_options.c +18 -8
@@ -1640,9 +1640,20 @@ eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)return -1 ; } -/* Parse the arguments for --log-level only */ +bool +eal_option_is_log (int opt) +{ +switch (opt) { +case OPT_LOG_LEVEL_NUM : +return true; +default : +return false; + } +} + +/* Parse all arguments looking for log related ones */ int -eal_log_level_parse (int argc,char *const argv[]) +eal_parse_log_options (int argc,char *const argv[]) {struct internal_config *internal_conf =eal_get_internal_configuration ();int option_index, opt;
@@ -1661,12 +1672,11 @@ eal_log_level_parse(int argc, char * const argv[])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 ; - } +if (!eal_option_is_log (opt)) +continue ; + +if (eal_parse_common_option (opt, optarg, internal_conf) <0 ) +return -1 ; }/* restore getopt lib */
lib/eal/common/eal_options.h +2 -1
@@ -96,7 +96,8 @@ enum {extern const char eal_short_options[];extern const struct option eal_long_options[]; -int eal_log_level_parse (int argc,char *const argv[]); +bool eal_option_is_log (int opt); +int eal_parse_log_options (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 +4 -4
@@ -393,8 +393,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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -575,8 +575,8 @@ 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); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);if (rte_eal_cpu_init () <0 ) {rte_eal_init_alert ("Cannot detect lcores." );
lib/eal/linux/eal.c +4 -4
@@ -611,8 +611,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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -951,8 +951,8 @@ 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); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);/* clone argv to report out later in telemetry */ eal_save_args (argc, argv);
lib/eal/windows/eal.c +4 -3
@@ -121,8 +121,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_parse_log_options() already handled this option */ +if (eal_option_is_log (opt))continue ; ret =eal_parse_common_option (opt, optarg, internal_conf);
@@ -254,7 +254,8 @@ rte_eal_init(int argc, char **argv)eal_log_init (NULL ,0 ); -eal_log_level_parse (argc, argv); +/* parse log options as early as possible */ +eal_parse_log_options (argc, argv);if (eal_create_cpu_map () <0 ) {rte_eal_init_alert ("Cannot discover CPU and NUMA." );
Signature · 1 line
2.47.0
PATCH v32 4/12 eal: do not log init failure twice
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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 | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-)
lib/eal/freebsd/eal.c +1 -2
@@ -530,8 +530,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
@@ -831,8 +831,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 +1 -2
@@ -182,8 +182,7 @@ 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); +EAL_LOG (ALERT ,"%s" , msg); }/* Stubs to enable EAL trace point compilation
Signature · 1 line
2.47.0
PATCH v32 5/12 eal: improve exit output log
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -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.47.0
PATCH v32 6/12 log: rework syslog handling
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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 adds syslog support to FreeBSD.
Log to syslog only if option is specified.
If no --syslog is given then use only standard error.
--- 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 | 6 +- doc/guides/rel_notes/release_24_11.rst | 6 + lib/eal/common/eal_common_options.c | 57 +-------- lib/eal/common/eal_internal_cfg.h | 1 - lib/eal/freebsd/eal.c | 1 - lib/eal/linux/eal.c | 8 +- lib/eal/windows/eal.c | 2 +- lib/log/log.c | 43 ++++--- lib/log/log_freebsd.c | 12 -- lib/log/log_internal.h | 11 +- lib/log/log_linux.c | 61 ---------- lib/log/log_private.h | 27 +++++ lib/log/log_syslog.c | 108 ++++++++++++++++++ lib/log/log_windows.c | 18 --- lib/log/meson.build | 6 +- lib/log/version.map | 2 +- 19 files changed, 220 insertions(+), 198 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
@@ -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
@@ -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
@@ -884,9 +884,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 +3 -3
@@ -5,9 +5,9 @@ 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. +By default, logs are sent only to standard error output of the process. +The syslog EAL option can be used to redirect to the stystem logger on Linux and FreeBSD. +In addition, the log can be redirected to a different stdio file stream. Log Levels ----------
doc/guides/rel_notes/release_24_11.rst +6 -0
@@ -114,6 +114,12 @@ New Features (and vice versa); freeing the same pointer twice in the same routine; freeing an object that was not created by allocation; etc. +* **Updated logging library** + + * The syslog option has changed. + By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. + Syslog is also supported on FreeBSD (but not on Windows). + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
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
@@ -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 +0 -1
@@ -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>
lib/eal/linux/eal.c +1 -7
@@ -1104,13 +1104,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 +1 -1
@@ -251,7 +251,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 );/* parse log options as early as possible */ eal_parse_log_options (argc, argv);
lib/log/log.c +20 -23
90 lines not on this page · raw message
lib/log/log_freebsd.c deleted +0 -12
@@ -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
@@ -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 +27 -0
@@ -0,0 +1,27 @@ +/* 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 +108 -0
108 lines not on this page · raw message
lib/log/log_windows.c deleted +0 -18
@@ -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
@@ -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
@@ -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.47.0
PATCH v32 7/12 eal: initialize log before everything else
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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.
--- doc/guides/rel_notes/release_24_11.rst | 2 ++ lib/eal/freebsd/eal.c | 13 ++++++++++--- lib/eal/linux/eal.c | 14 +++++++++----- lib/eal/windows/eal.c | 10 +++++++--- 4 files changed, 28 insertions(+), 11 deletions(-)
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -116,6 +116,8 @@ New Features * **Updated logging library** + * The log subsystem is initialized earlier in startup so all messages go through the library. + * The syslog option has changed. By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows).
lib/eal/freebsd/eal.c +10 -3
@@ -53,6 +53,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)
@@ -547,6 +548,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_parse_log_options (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." );
@@ -573,9 +583,6 @@ rte_eal_init(int argc, char **argv)/* clone argv to report out later in telemetry */ eal_save_args (argc, argv); -/* parse log options as early as possible */ -eal_parse_log_options (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
@@ -927,6 +927,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_parse_log_options (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." );
@@ -950,9 +959,6 @@ rte_eal_init(int argc, char **argv)eal_reset_internal_config (internal_conf); -/* parse log options as early as possible */ -eal_parse_log_options (argc, argv); -/* clone argv to report out later in telemetry */ eal_save_args (argc, argv);
@@ -1104,8 +1110,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 +7 -3
@@ -251,10 +251,14 @@ 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 ); +/* setup log as early as possible */ +if (eal_parse_log_options (argc, argv) <0 ) { +rte_eal_init_alert ("invalid log arguments." ); + rte_errno =EINVAL ; +return -1 ; + } -/* parse log options as early as possible */ -eal_parse_log_options (argc, argv); +eal_log_init (NULL );if (eal_create_cpu_map () <0 ) {rte_eal_init_alert ("Cannot discover CPU and NUMA." );
Signature · 1 line
2.47.0
PATCH v32 8/12 log: add hook for printing log messages
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
@@ -29,16 +29,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 {
@@ -75,6 +80,7 @@ int rte_openlog_stream(FILE *f) { rte_logs.file = f; + rte_logs.print_func = vfprintf;return 0 ; }
@@ -471,7 +477,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.47.0
PATCH v32 9/12 log: add timestamp option
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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
Note: Windows does not have localtime_r but it does have a similar function that can be used instead. Add it to rte_os_shim.h.
--- app/test/test_eal_flags.c | 24 +++ doc/guides/prog_guide/log_lib.rst | 28 +++ doc/guides/rel_notes/release_24_11.rst | 2 + lib/eal/common/eal_common_options.c | 14 +- lib/eal/common/eal_options.h | 2 + lib/eal/windows/include/rte_os_shim.h | 10 ++ lib/log/log.c | 13 +- lib/log/log_internal.h | 9 + lib/log/log_private.h | 6 + lib/log/log_timestamp.c | 240 +++++++++++++++++++++++++ lib/log/meson.build | 1 + lib/log/version.map | 1 + 12 files changed, 344 insertions(+), 6 deletions(-) create mode 100644 lib/log/log_timestamp.c
app/test/test_eal_flags.c +24 -0
@@ -1055,6 +1055,18 @@ 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 +1174,18 @@ 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 +28 -0
@@ -110,3 +110,31 @@ 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 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.
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -122,6 +122,8 @@ New Features By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows). + * Log messages can be timestamped with ``--log-timestamp`` option. + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
lib/eal/common/eal_common_options.c +12 -2
@@ -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 },
@@ -1599,6 +1600,7 @@ eal_option_is_log(int opt) {switch (opt) {case OPT_LOG_LEVEL_NUM : +case OPT_LOG_TIMESTAMP_NUM :case OPT_SYSLOG_NUM :return true;default :
@@ -1850,7 +1852,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 --"
@@ -1858,7 +1860,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 : {
@@ -2225,6 +2234,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
@@ -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/windows/include/rte_os_shim.h +10 -0
@@ -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 +9 -4
@@ -17,13 +17,13 @@#include <rte_log.h> #include <rte_per_lcore.h> -#include "log_internal.h" -#include "log_private.h" -#ifdef RTE_EXEC_ENV_WINDOWS -#define strdup _strdup +#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;
@@ -513,6 +513,11 @@ eal_log_init(const char *id)if (logf)rte_openlog_stream (logf); +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
@@ -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
@@ -24,4 +24,10 @@ bool log_syslog_enabled(void);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 +240 -0
240 lines not on this page · raw message
lib/log/meson.build +1 -0
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_timestamp.c', ) if not is_windows
lib/log/version.map +1 -0
@@ -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.47.0
PATCH v32 10/12 log: support systemd journal
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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/rel_notes/release_24_11.rst | 4 + lib/log/log.c | 31 +++-- lib/log/log_internal.h | 3 + lib/log/log_journal.c | 153 +++++++++++++++++++++++++ lib/log/log_private.h | 16 +++ lib/log/meson.build | 4 + lib/log/version.map | 1 + 7 files changed, 200 insertions(+), 12 deletions(-) create mode 100644 lib/log/log_journal.c
doc/guides/rel_notes/release_24_11.rst +4 -0
@@ -118,6 +118,10 @@ New Features * The log subsystem is initialized earlier in startup so all messages go through the library. + * If the application is a systemd service and the log output is being sent to standard error + then DPDK will switch to journal native protocol. + This allows the more data such as severity to be sent. + * The syslog option has changed. By default, messages are no longer sent to syslog unless the ``--syslog`` option is specified. Syslog is also supported on FreeBSD (but not on Windows).
lib/log/log.c +19 -12
@@ -505,18 +505,25 @@ rte_log(uint32_t level, uint32_t logtype, const char *format, ...)void eal_log_init (const char *id) { -FILE *logf =NULL ; - -if (log_syslog_enabled ()) - logf =log_syslog_open (id); - -if (logf) -rte_openlog_stream (logf); - -if (log_timestamp_enabled ()) - rte_logs.print_func = log_print_with_timestamp; -else - rte_logs.print_func = vfprintf; +/* If user has already set a log stream, then use it. */ +if (rte_logs.file ==NULL ) { +FILE *logf =NULL ; + +/* if stderr is associated with systemd environment */ +if (log_journal_enabled ()) + logf =log_journal_open (id); +/* If --syslog option was passed */ +else if (log_syslog_enabled ()) + logf =log_syslog_open (id); + +/* if either syslog or journal is used, then no special handling */ +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; + }#if RTE_LOG_DP_LEVEL >=RTE_LOG_DEBUG RTE_LOG(NOTICE, EAL,
lib/log/log_internal.h +3 -0
@@ -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 +153 -0
153 lines not on this page · raw message
lib/log/log_private.h +16 -0
@@ -24,6 +24,22 @@ 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 +static inline bool +log_journal_enabled (void ) +{ +return false; +} +static inline FILE * +log_journal_open(const char *id __rte_unused) +{ +return NULL ; +} +#endif /* !RTE_EXEC_ENV_LINUX */ +bool log_timestamp_enabled (void );ssize_t log_timestamp (char *tsbuf,size_t tsbuflen);
lib/log/meson.build +4 -0
@@ -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
@@ -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.47.0
PATCH v32 11/12 log: colorize log output
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
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.
Note: add fileno() and isatty() to the Windows wrapper.
--- app/test/test_eal_flags.c | 24 +++ doc/guides/prog_guide/log_lib.rst | 24 +++ doc/guides/rel_notes/release_24_11.rst | 2 + lib/eal/common/eal_common_options.c | 11 ++ lib/eal/common/eal_options.h | 2 + lib/eal/windows/include/rte_os_shim.h | 2 + lib/log/log.c | 23 ++- lib/log/log_color.c | 214 +++++++++++++++++++++++++ lib/log/log_internal.h | 5 + lib/log/log_private.h | 8 + lib/log/meson.build | 1 + lib/log/version.map | 1 + 12 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 lib/log/log_color.c
app/test/test_eal_flags.c +24 -0
@@ -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 */ if (launch_proc (argv0) ==0 ) {
@@ -1186,6 +1198,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=never 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);rmdir (hugepath_dir2);
doc/guides/prog_guide/log_lib.rst +24 -0
@@ -59,6 +59,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 -------------------------------------------
@@ -138,3 +139,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.
doc/guides/rel_notes/release_24_11.rst +2 -0
@@ -128,6 +128,8 @@ New Features * Log messages can be timestamped with ``--log-timestamp`` option. + * Log messages can be colorized with the ``--log-color`` option. + * **Updated Marvell cnxk mempool driver.** * Added mempool driver support for CN20K SoC.
lib/eal/common/eal_common_options.c +11 -0
@@ -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 },
@@ -1599,6 +1600,7 @@ bool eal_option_is_log(int opt) {switch (opt) { +case OPT_LOG_COLOR_NUM :case OPT_LOG_LEVEL_NUM :case OPT_LOG_TIMESTAMP_NUM :case OPT_SYSLOG_NUM :
@@ -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 ) {
@@ -2235,6 +2245,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
@@ -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/eal/windows/include/rte_os_shim.h +2 -0
@@ -30,6 +30,8 @@#define write (fd, buf, n) _write(fd, buf, n)#define close (fd) _close(fd)#define unlink (path) _unlink(path) +#define fileno (f) _fileno(f) +#define isatty (fd) _isatty(fd)#define IPVERSION 4
lib/log/log.c +18 -5
@@ -12,6 +12,7 @@#include <regex.h> #include <fnmatch.h> #include <sys/queue.h> +#include <unistd.h> #include <rte_common.h> #include <rte_log.h>
@@ -517,12 +518,24 @@ eal_log_init(const char *id) logf =log_syslog_open (id);/* if either syslog or journal is used, then no special handling */ -if (logf) +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
lib/log/log_color.c new file +214 -0
214 lines not on this page · raw message
lib/log/log_internal.h +5 -0
@@ -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
@@ -46,4 +46,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
@@ -4,6 +4,7 @@ includes += global_inc sources = files( 'log.c', + 'log_color.c', 'log_timestamp.c', )
lib/log/version.map +1 -0
@@ -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.47.0
PATCH v32 12/12 maintainers: update for log library
In reply to David MarchandFrom: Stephen Hemminger <[email protected]>
"You touch it you own it".
Add myself as maintainer for log library.
--- MAINTAINERS | 1 + 1 file changed, 1 insertion(+)
MAINTAINERS +1 -0
@@ -193,6 +193,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.47.0
David Marchand
AppliedRe: [PATCH v32 00/12] Log library enhancements
In reply to David MarchandQuoted 37 lines · David Marchand
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 Stephen as maintainer for log because by now have added more than previous authors.
Quoted 6 lines
Resending for CI:
Changes since v31:
- rebased,
- fixed build with MSVC: escape character was restored to \033 (used until v25) instead of \e,
Applied, thanks.
Signature · 1 line
David Marchand