From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4CFC445BC3; Fri, 25 Oct 2024 17:33:55 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D21564021F; Fri, 25 Oct 2024 17:33:54 +0200 (CEST) Received: from mail-oa1-f50.google.com (mail-oa1-f50.google.com [209.85.160.50]) by mails.dpdk.org (Postfix) with ESMTP id AECB440156 for ; Fri, 25 Oct 2024 17:33:52 +0200 (CEST) Received: by mail-oa1-f50.google.com with SMTP id 586e51a60fabf-288d4da7221so1228414fac.1 for ; Fri, 25 Oct 2024 08:33:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=weka.io; s=google; t=1729870432; x=1730475232; darn=dpdk.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=4dz4DAWihdcLUotzYdkJJAVAia4+RNj7ZkvOFhxJiNw=; b=S5K3clywzZTd9zVHNXUmILWK9mko34djbs7hr+1eGoPN/OjBlQQVo0mgK3OueQ35mG dun1xWUcIIOxlMA+lWFCmHSW2f9J304bxVH2e32ixBTARkPZF/bxoPyn9eIDd3omyqHx 8Tm4li7Xv0a+bkVNdnLPuuXyyqTF3WHsfrfGs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729870432; x=1730475232; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=4dz4DAWihdcLUotzYdkJJAVAia4+RNj7ZkvOFhxJiNw=; b=KjggJWOTPLkTRdke0elkF7Mh6oX7DfR6tV4ISBgt+rWwXbHRjkx7zyZl8qJpvHpmEn gzJOXW/a+VCnbclM0DTlVSufkt+4qElbONuRu+ikuLPBm4Hf+l1zlNnPZphJXDdMbPag 9f6a8efu5qGMf6C4P0yOnmwQy8tl1phuZ9EhH25lWX+L8BkvrobTRpLvSvCD0gZmc3ea 1CX/Q0ayLb26kygxZGMi/khnyKxQoCjX07V8ao3vxTBx/LhzysLkkC+mov2ZDFxnpLWz SPBFCXEFiQhNa+LWIhHv6sj2POLZvJwxzQwiA0wINusSauM1v4WmWS+zCpTxWB5CLtPg eh9Q== X-Gm-Message-State: AOJu0YzPerPcH5zovPeim97k36c8JLf23mqozgb5N2Nxtf7kBfTVw39h 11zPPw0LVRzt7sDx01a+8dQ1FjysCzxSNnhW+Z+qXG/7d+jP3pO+zD0TYvEXb8KSepwBGtY1Up8 esy6OCQMEgBXSdslU7PGE7OcR04J3IVmWpz14y/a4kio/6ldwkP55VSxORsc/xl/XcLgDo6wxe0 jLf36Be23v9VaogCIlaJPugIFkcZA5FcAR3BEvxFgAQ8EUNOFxv/GegtZfuES2z+8FrdqBAindr A== X-Google-Smtp-Source: AGHT+IFwWjFX+Z+2ohcXsPjmAkLqFgd8OKB1KFVIM4/mja8d9IxpbSMQ/Ln81oUnNNaGxlR7KwY41ukc75F8C07ptVY= X-Received: by 2002:a05:6871:284:b0:268:880c:9de3 with SMTP id 586e51a60fabf-28ced27ad76mr5874168fac.14.1729870431726; Fri, 25 Oct 2024 08:33:51 -0700 (PDT) MIME-Version: 1.0 References: <20200814173441.23086-1-stephen@networkplumber.org> <20241024190818.172863-1-stephen@networkplumber.org> <20241024190818.172863-12-stephen@networkplumber.org> In-Reply-To: <20241024190818.172863-12-stephen@networkplumber.org> From: Baruch Even Date: Fri, 25 Oct 2024 18:33:40 +0300 Message-ID: Subject: Re: [PATCH v28 11/13] log: add support for systemd journal To: Stephen Hemminger Cc: dev@dpdk.org, =?UTF-8?Q?Morten_Br=C3=B8rup?= , Bruce Richardson Content-Type: multipart/alternative; boundary="000000000000974ece06254ed88a" X-CLOUD-SEC-AV-Sent: true X-CLOUD-SEC-AV-Info: weka,google_mail,monitor X-Gm-Spam: 0 X-Gm-Phishy: 0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org --000000000000974ece06254ed88a Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable 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. On Thu, Oct 24, 2024 at 10:09=E2=80=AFPM Stephen Hemminger < stephen@networkplumber.org> wrote: > 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://url.avanan.click/v2/r01/___https://systemd.io/JOURNAL_NATIVE_PROT= OCOL/___.YXAzOndla2E6YTpnOjc1MmU1YTVhODIzMWJiMTdkNTBhNzE4MDVhNDc2MTBhOjc6MT= NlMjpkODkwMzM0ZTExZTQyZTBmZDY2NmI4YmRjMzY1Nzk1NTJlZjYyMWI0MjE1MjYyOTU4MTg3Y= jE3YjA1Y2NjMDA4OnA6VDpO > > Signed-off-by: Stephen Hemminger > Acked-by: Morten Br=C3=B8rup > Acked-by: Bruce Richardson > --- > 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 > > diff --git a/lib/log/log.c b/lib/log/log.c > index 7bf4548858..343f9d77b7 100644 > --- a/lib/log/log.c > +++ b/lib/log/log.c > @@ -508,13 +508,14 @@ eal_log_init(const char *id) > { > FILE *logf =3D NULL; > > - if (log_syslog_enabled()) > + if (log_journal_enabled()) > + logf =3D log_journal_open(id); > + else if (log_syslog_enabled()) > logf =3D log_syslog_open(id); > > if (logf) > rte_openlog_stream(logf); > - > - if (log_timestamp_enabled()) > + else if (log_timestamp_enabled()) > rte_logs.print_func =3D log_print_with_timestamp; > else > rte_logs.print_func =3D vfprintf; > diff --git a/lib/log/log_internal.h b/lib/log/log_internal.h > index 8ef195a6ec..731c099984 100644 > --- a/lib/log/log_internal.h > +++ b/lib/log/log_internal.h > @@ -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. > */ > diff --git a/lib/log/log_journal.c b/lib/log/log_journal.c > new file mode 100644 > index 0000000000..43341aa233 > --- /dev/null > +++ b/lib/log/log_journal.c > @@ -0,0 +1,154 @@ > +/* SPDX-License-Identifier: BSD-3-Clause */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#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_PROT= OCOL/___.YXAzOndla2E6YTpnOjc1MmU1YTVhODIzMWJiMTdkNTBhNzE4MDVhNDc2MTBhOjc6NT= QxZDoyMWQ3NGFjZGMwYWE0M2RhZTM4OTc0ZmJjNGY1NzFkZTFlNTZmMTEwM2I3ZDNhN2U3ZDkxN= zFmZjg4ODU3NGQxOnA6VDpO > + * > + * Uses writev() to ensure that whole log message is in one datagram > + */ > +static int > +journal_send(int fd, const char *buf, size_t len) > +{ > + struct iovec iov[4]; > + unsigned int n =3D 0; > + int priority =3D rte_log_cur_msg_loglevel() - 1; > + char msg[] =3D "MESSAGE=3D"; > + char newline =3D '\n'; > + char pbuf[32]; /* "PRIORITY=3DN\n" */ > + > + iov[n].iov_base =3D msg; > + iov[n++].iov_len =3D strlen(msg); > + > + iov[n].iov_base =3D (char *)(uintptr_t)buf; > + iov[n++].iov_len =3D len; > + > + /* if message doesn't end with newline, one will be applied. */ > + if (buf[len - 1] !=3D '\n') { > + iov[n].iov_base =3D &newline; > + iov[n++].iov_len =3D 1; > + } > + > + /* priority value between 0 ("emerg") and 7 ("debug") */ > + iov[n].iov_base =3D pbuf; > + iov[n++].iov_len =3D snprintf(pbuf, sizeof(pbuf), > + "PRIORITY=3D%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 =3D (uintptr_t)c; > + > + return journal_send(fd, buf, size); > +} > + > +static int > +journal_log_close(void *c) > +{ > + int fd =3D (uintptr_t)c; > + > + close(fd); > + return 0; > +} > + > +static cookie_io_functions_t journal_log_func =3D { > + .write =3D journal_log_write, > + .close =3D journal_log_close, > +}; > + > +/* > + * Check if stderr is going to system journal. > + * This is the documented way to handle systemd journal > + * > + * See: > https://url.avanan.click/v2/r01/___https://systemd.io/JOURNAL_NATIVE_PROT= OCOL/___.YXAzOndla2E6YTpnOjc1MmU1YTVhODIzMWJiMTdkNTBhNzE4MDVhNDc2MTBhOjc6Nj= A4MzpiZGFiZDNiOGRhZDVhMDBkOGI1N2NmZTBjYjUyYjYzNmY5NTU3NGMyZjVmOTk2MTA4YjQxN= zMxNDBmNzZhYWE4OnA6VDpO > + */ > +bool > +log_journal_enabled(void) > +{ > + char *jenv, *endp =3D NULL; > + struct stat st; > + unsigned long dev, ino; > + > + jenv =3D getenv("JOURNAL_STREAM"); > + if (jenv =3D=3D NULL) > + return false; > + > + if (fstat(STDERR_FILENO, &st) < 0) > + return false; > + > + /* systemd sets colon-separated list of device and inode number *= / > + dev =3D strtoul(jenv, &endp, 10); > + if (endp =3D=3D NULL || *endp !=3D ':') > + return false; /* missing colon */ > + > + ino =3D strtoul(endp + 1, NULL, 10); > + > + return dev =3D=3D st.st_dev && ino =3D=3D 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 =3D { > + .sun_family =3D AF_UNIX, > + .sun_path =3D "/run/systemd/journal/socket", > + }; > + int jfd =3D -1; > + > + len =3D snprintf(syslog_id, sizeof(syslog_id), > + "SYSLOG_IDENTIFIER=3D%s\nSYSLOG_PID=3D%u", id, > getpid()); > + > + /* Detect truncation of message and fallback to no journal */ > + if (len >=3D (int)sizeof(syslog_id)) > + return NULL; > + > + jfd =3D 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) !=3D len) { > + perror("write"); > + goto error; > + } > + > + /* redirect other log messages to journal */ > + log_stream =3D fopencookie((void *)(uintptr_t)jfd, "w", > journal_log_func); > + if (log_stream !=3D NULL) > + return log_stream; > + > +error: > + close(jfd); > + return NULL; > +} > diff --git a/lib/log/log_private.h b/lib/log/log_private.h > index 86eaf3f910..37895949f6 100644 > --- a/lib/log/log_private.h > +++ b/lib/log/log_private.h > @@ -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); > > diff --git a/lib/log/log_syslog.c b/lib/log/log_syslog.c > index 7d29e3a00f..c23b19fe89 100644 > --- a/lib/log/log_syslog.c > +++ b/lib/log/log_syslog.c > @@ -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 =3D=3D NULL) { > + log_facility =3D LOG_DAEMON; > + return 0; > + } > + > for (i =3D 0; i < RTE_DIM(facilitys); i++) { > if (!strcmp(name, facilitys[i].name)) { > log_facility =3D facilitys[i].value; > diff --git a/lib/log/meson.build b/lib/log/meson.build > index 4ac232786e..86e4452b19 100644 > --- a/lib/log/meson.build > +++ b/lib/log/meson.build > @@ -11,4 +11,8 @@ if not is_windows > sources +=3D files('log_syslog.c') > endif > > +if is_linux > + sources +=3D files('log_journal.c') > +endif > + > headers =3D files('rte_log.h') > diff --git a/lib/log/version.map b/lib/log/version.map > index 8be6907840..800d3943bc 100644 > --- a/lib/log/version.map > +++ b/lib/log/version.map > @@ -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 > > --=20 Baruch Even Platform Technical Lead at WEKA E baruch@weka.io* =C2=AD*W https://www.weka.io* =C2=AD* [image: App Banner Image] --000000000000974ece06254ed88a Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Can we have an option to disable journal auto-detecti= on?
In my case I want to redirect the DPDK to our own tracing inf= rastructure and for that I use the fopencookie myself and redirect it to ou= r own system. The journal will force it out and I'll need to ensure tha= t the environment variable is not set, which is doable but I'd rather n= ot need to mess with the environment and just set a flag in dpdk options to= disable the journal.

On Thu, Oct 24, 2024 at 10:09=E2=80=AFPM Ste= phen Hemminger <stephen@ne= tworkplumber.org> wrote:
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.=C2=A0 Rather than having a dependency on libsystemd,
just use the protocol directly as defined in:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 https://url.avanan.click/v2/r01/___https://systemd.= io/JOURNAL_NATIVE_PROTOCOL/___.YXAzOndla2E6YTpnOjc1MmU1YTVhODIzMWJiMTdkNTBh= NzE4MDVhNDc2MTBhOjc6MTNlMjpkODkwMzM0ZTExZTQyZTBmZDY2NmI4YmRjMzY1Nzk1NTJlZjY= yMWI0MjE1MjYyOTU4MTg3YjE3YjA1Y2NjMDA4OnA6VDpO

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Morten Br=C3=B8rup <mb@smartsharesystems.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
=C2=A0lib/log/log.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 |=C2=A0 =C2=A07 +- =C2=A0lib/log/log_internal.h |=C2=A0 =C2=A03 +
=C2=A0lib/log/log_journal.c=C2=A0 | 154 +++++++++++++++++++++++++++++++++++= ++++++
=C2=A0lib/log/log_private.h=C2=A0 |=C2=A0 14 ++++
=C2=A0lib/log/log_syslog.c=C2=A0 =C2=A0|=C2=A0 =C2=A09 +++
=C2=A0lib/log/meson.build=C2=A0 =C2=A0 |=C2=A0 =C2=A04 ++
=C2=A0lib/log/version.map=C2=A0 =C2=A0 |=C2=A0 =C2=A01 +
=C2=A07 files changed, 189 insertions(+), 3 deletions(-)
=C2=A0create mode 100644 lib/log/log_journal.c

diff --git a/lib/log/log.c b/lib/log/log.c
index 7bf4548858..343f9d77b7 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -508,13 +508,14 @@ eal_log_init(const char *id)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0 FILE *logf =3D NULL;

-=C2=A0 =C2=A0 =C2=A0 =C2=A0if (log_syslog_enabled())
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (log_journal_enabled())
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0logf =3D log_journa= l_open(id);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0else if (log_syslog_enabled())
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 logf =3D log_syslog= _open(id);

=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (logf)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 rte_openlog_stream(= logf);
-
-=C2=A0 =C2=A0 =C2=A0 =C2=A0if (log_timestamp_enabled())
+=C2=A0 =C2=A0 =C2=A0 =C2=A0else if (log_timestamp_enabled())
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 rte_logs.print_func= =3D log_print_with_timestamp;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 else
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 rte_logs.print_func= =3D vfprintf;
diff --git a/lib/log/log_internal.h b/lib/log/log_internal.h
index 8ef195a6ec..731c099984 100644
--- a/lib/log/log_internal.h
+++ b/lib/log/log_internal.h
@@ -35,6 +35,9 @@ int eal_log_save_pattern(const char *pattern, uint32_t le= vel);
=C2=A0__rte_internal
=C2=A0int eal_log_syslog(const char *name);

+__rte_internal
+int eal_log_journal(const char *opt);
+
=C2=A0/*
=C2=A0 * Convert log level to string.
=C2=A0 */
diff --git a/lib/log/log_journal.c b/lib/log/log_journal.c
new file mode 100644
index 0000000000..43341aa233
--- /dev/null
+++ b/lib/log/log_journal.c
@@ -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_P= ROTOCOL/___.YXAzOndla2E6YTpnOjc1MmU1YTVhODIzMWJiMTdkNTBhNzE4MDVhNDc2MTBhOjc= 6NTQxZDoyMWQ3NGFjZGMwYWE0M2RhZTM4OTc0ZmJjNGY1NzFkZTFlNTZmMTEwM2I3ZDNhN2U3ZD= kxNzFmZjg4ODU3NGQxOnA6VDpO
+ *
+ * Uses writev() to ensure that whole log message is in one datagram
+ */
+static int
+journal_send(int fd, const char *buf, size_t len)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0struct iovec iov[4];
+=C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned int n =3D 0;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int priority =3D rte_log_cur_msg_loglevel() - 1= ;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char msg[] =3D "MESSAGE=3D";
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char newline =3D '\n';
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char pbuf[32];=C2=A0 /* "PRIORITY=3DN\n&qu= ot; */
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0iov[n].iov_base =3D msg;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0iov[n++].iov_len =3D strlen(msg);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0iov[n].iov_base =3D (char *)(uintptr_t)buf;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0iov[n++].iov_len =3D len;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* if message doesn't end with newline, one= will be applied. */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (buf[len - 1] !=3D '\n') {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0iov[n].iov_base =3D= &newline;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0iov[n++].iov_len = =3D 1;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* priority value between 0 ("emerg")= and 7 ("debug") */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0iov[n].iov_base =3D pbuf;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0iov[n++].iov_len =3D snprintf(pbuf, sizeof(pbuf= ),
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"PRIORITY=3D%d\n&q= uot;, priority);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return 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)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int fd =3D (uintptr_t)c;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return journal_send(fd, buf, size);
+}
+
+static int
+journal_log_close(void *c)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int fd =3D (uintptr_t)c;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0close(fd);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
+}
+
+static cookie_io_functions_t journal_log_func =3D {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0.write =3D journal_log_write,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0.close =3D journal_log_close,
+};
+
+/*
+ * Check if stderr is going to system journal.
+ * This is the documented way to handle systemd journal
+ *
+ * See: https://url.avanan.click/v2/r01/___https://systemd.io/JOURNAL_NATIVE_P= ROTOCOL/___.YXAzOndla2E6YTpnOjc1MmU1YTVhODIzMWJiMTdkNTBhNzE4MDVhNDc2MTBhOjc= 6NjA4MzpiZGFiZDNiOGRhZDVhMDBkOGI1N2NmZTBjYjUyYjYzNmY5NTU3NGMyZjVmOTk2MTA4Yj= QxNzMxNDBmNzZhYWE4OnA6VDpO
+ */
+bool
+log_journal_enabled(void)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char *jenv, *endp =3D NULL;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0struct stat st;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned long dev, ino;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0jenv =3D getenv("JOURNAL_STREAM"); +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (jenv =3D=3D NULL)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return false;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (fstat(STDERR_FILENO, &st) < 0)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return false;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* systemd sets colon-separated list of device = and inode number */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0dev =3D strtoul(jenv, &endp, 10);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (endp =3D=3D NULL || *endp !=3D ':')=
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return false;=C2=A0= =C2=A0/* missing colon */
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0ino =3D strtoul(endp + 1, NULL, 10);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return dev =3D=3D st.st_dev && ino =3D= =3D st.st_ino;
+}
+
+/* Connect to systemd's journal service */
+FILE *log_journal_open(const char *id)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0char syslog_id[PATH_MAX];
+=C2=A0 =C2=A0 =C2=A0 =C2=A0FILE *log_stream;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int len;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0struct sockaddr_un sun =3D {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0.sun_family =3D AF_= UNIX,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0.sun_path =3D "= ;/run/systemd/journal/socket",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0};
+=C2=A0 =C2=A0 =C2=A0 =C2=A0int jfd =3D -1;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0len =3D snprintf(syslog_id, sizeof(syslog_id),<= br> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 "SYSLOG_IDENTIFIER=3D%s\nSYSLOG_PID=3D%u", id, getpid());
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* Detect truncation of message and fallback to= no journal */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (len >=3D (int)sizeof(syslog_id))
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return NULL;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0jfd =3D socket(AF_UNIX, SOCK_DGRAM, 0);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (jfd < 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0perror("socket= ");
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto error;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (connect(jfd, (struct sockaddr *)&sun, s= izeof(sun)) < 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0perror("connec= t");
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto error;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* Send identifier as first message */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (write(jfd, syslog_id, len) !=3D len) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0perror("write&= quot;);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0goto error;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* redirect other log messages to journal */ +=C2=A0 =C2=A0 =C2=A0 =C2=A0log_stream =3D fopencookie((void *)(uintptr_t)j= fd, "w", journal_log_func);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (log_stream !=3D NULL)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return log_stream;<= br> +
+error:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0close(jfd);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return NULL;
+}
diff --git a/lib/log/log_private.h b/lib/log/log_private.h
index 86eaf3f910..37895949f6 100644
--- a/lib/log/log_private.h
+++ b/lib/log/log_private.h
@@ -22,6 +22,20 @@ bool log_syslog_enabled(void);
=C2=A0FILE *log_syslog_open(const char *id);
=C2=A0#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)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return false;
+}
+static inline FILE *log_journal_open(const char *id __rte_unused)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return NULL;
+}
+#endif /* !RTE_EXEC_ENV_LINUX */
+
=C2=A0bool log_timestamp_enabled(void);
=C2=A0ssize_t log_timestamp(char *tsbuf, size_t tsbuflen);

diff --git a/lib/log/log_syslog.c b/lib/log/log_syslog.c
index 7d29e3a00f..c23b19fe89 100644
--- a/lib/log/log_syslog.c
+++ b/lib/log/log_syslog.c
@@ -18,6 +18,10 @@

=C2=A0static int log_facility;

+/*
+ * Usable list of facilities
+ * Skip kern, mark, and security
+ */
=C2=A0static const struct {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 const char *name;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 int value;
@@ -48,6 +52,11 @@ eal_log_syslog(const char *name)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0 unsigned int i;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (name =3D=3D NULL) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0log_facility =3D LO= G_DAEMON;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (i =3D 0; i < RTE_DIM(facilitys); i++) {=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (!strcmp(name, f= acilitys[i].name)) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 log_facility =3D facilitys[i].value;
diff --git a/lib/log/meson.build b/lib/log/meson.build
index 4ac232786e..86e4452b19 100644
--- a/lib/log/meson.build
+++ b/lib/log/meson.build
@@ -11,4 +11,8 @@ if not is_windows
=C2=A0 =C2=A0 =C2=A0sources +=3D files('log_syslog.c')
=C2=A0endif

+if is_linux
+=C2=A0 =C2=A0 sources +=3D files('log_journal.c')
+endif
+
=C2=A0headers =3D files('rte_log.h')
diff --git a/lib/log/version.map b/lib/log/version.map
index 8be6907840..800d3943bc 100644
--- a/lib/log/version.map
+++ b/lib/log/version.map
@@ -26,6 +26,7 @@ INTERNAL {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 global:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 eal_log_init;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0eal_log_journal; # WINDOWS_NO_EXPORT
=C2=A0 =C2=A0 =C2=A0 =C2=A0 eal_log_level2str;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 eal_log_save_pattern;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 eal_log_save_regexp;
--
2.45.2



--
=
Baruch Even
Platform Technical Lead= at=C2=A0WEKA
E=C2=A0baruch@weka.io=E2=80= =85=C2=ADW=C2=A0https://www.weka.io=E2=80=85=C2=AD

= 3D"App

= =C2=A0
--000000000000974ece06254ed88a--