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 52CC843D5A; Tue, 26 Mar 2024 18:37:51 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 44D2D42D27; Tue, 26 Mar 2024 18:36:26 +0100 (CET) Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) by mails.dpdk.org (Postfix) with ESMTP id E01F541153 for ; Tue, 26 Mar 2024 18:36:17 +0100 (CET) Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-6e88e4c8500so4120904b3a.2 for ; Tue, 26 Mar 2024 10:36:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1711474577; x=1712079377; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cm7mVE++Nm52YxNTfrtG5Pgi3cLHR6O+yO99pXua/HY=; b=gwNHSXqiiBiQyTfjUO41C38J9UNaTTWF+HwSCekeI6gfI15PmGRhac5d0UKJ2RbSzh 62HDpvYCg8yeogJ/IPkAGOLoIerf7FZfRJyr3kGfo7lQ+qNSwV7396dWu6UBxT5H33f6 Qh254AEehihhMFsqSXrbzRtic9/mIlYZtctt0wkOcnMPsKTsFGvPh+KuiQVcQYfv7WMY 4GW7TXbRLgZ2x5B6jFYnAwU+obUCmobgiangUNxllONFLK6ORpVXolFgfNL8J+t5lugX EIVOOqnRIHwDO5gL/GBkJvXoyMdArdSb6OaXThOOkG/4/0hyoyNbZlRUri2KYNtGKWnx 4Jlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711474577; x=1712079377; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cm7mVE++Nm52YxNTfrtG5Pgi3cLHR6O+yO99pXua/HY=; b=Ydg52EXdEpMJ8YLT/OZ5x7nCZ2IMC19W1VO2js06Y1aLUSmpyKDDpaY7d926CiifKB Lc7/qpZbKyDE6fOA1PRApWLMZoYj2ju+0+mi9csSuF+xMfUuZzVXP584v0jeJ+H7qhL+ kYXm052NFLmnZmFIHCqeuKpiGV8e2cyy2m4IX6SHfB+uYdqfCNDjTmByvpqS2FumiFfF 9RM66uzdqHFzSSQDO0Tng6b2PR1z+IkNugiOmcP+VjHyi79IbZXgOFfJBuC+Eat4Fir4 Mibff7BPB+f1XDoIscY2XGxkbCk7G8W8K77h2k710Wy/8XPzWKEHFDo+QbewwxiVh8zs coKw== X-Gm-Message-State: AOJu0Yw5IzrwBqc1d1gVOUmkT44I6sxSZGmVDh4EfnQ2I0iTfiouWN/h 9aFTr8kJiXVHt9KgADNas9ei8i8ejb3oiJhK0u369m3Qm+2ipZ9K97yORIdg0KPO7QX4EUszSh0 D X-Google-Smtp-Source: AGHT+IHdnGEY/Xy3m10N92oUjp8uZBa1J0RIMgxVOkSp7a2NLjZnCKH3Y1m8vzMyZAojFE8u64lZdg== X-Received: by 2002:a05:6a00:1482:b0:6ea:acbe:5188 with SMTP id v2-20020a056a00148200b006eaacbe5188mr3643829pfu.32.1711474577013; Tue, 26 Mar 2024 10:36:17 -0700 (PDT) Received: from hermes.local (204-195-123-203.wavecable.com. [204.195.123.203]) by smtp.gmail.com with ESMTPSA id u6-20020aa78386000000b006e58da8bb6asm6205546pfm.132.2024.03.26.10.36.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Mar 2024 10:36:16 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v14 14/15] log: add support for systemd journal Date: Tue, 26 Mar 2024 10:34:34 -0700 Message-ID: <20240326173552.97249-15-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240326173552.97249-1-stephen@networkplumber.org> References: <20200814173441.23086-1-stephen@networkplumber.org> <20240326173552.97249-1-stephen@networkplumber.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 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/ Signed-off-by: Stephen Hemminger --- lib/log/log.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 2 deletions(-) diff --git a/lib/log/log.c b/lib/log/log.c index d8974c66db..8e2319b3f0 100644 --- a/lib/log/log.c +++ b/lib/log/log.c @@ -17,6 +17,10 @@ #include #else #include +#include +#include +#include +#include #endif #include @@ -56,6 +60,7 @@ static struct rte_logs { FILE *file; /**< Output file set by rte_openlog_stream, or NULL. */ #ifndef RTE_EXEC_ENV_WINDOWS enum eal_log_syslog syslog_opt; + int journal_fd; #endif log_print_t print_func; @@ -758,6 +763,146 @@ static cookie_io_functions_t syslog_log_func = { .write = syslog_log_write, .close = syslog_log_close, }; + +/* + * send message using journal protocol to journald + */ +static int +journal_send(uint32_t level, const char *buf, size_t len) +{ + struct iovec iov[3]; + char msg[] = "MESSAGE="; + char prio[32]; + int ret; + + iov[0].iov_base = msg; + iov[0].iov_len = strlen(msg); + + iov[1].iov_base = (char *)(uintptr_t)buf; + iov[1].iov_len = len; + + /* priority value between 0 ("emerg") and 7 ("debug") */ + iov[2].iov_base = prio; + iov[2].iov_len = snprintf(prio, sizeof(prio), + "PRIORITY=%i\n", level - 1); + + ret = writev(rte_logs.journal_fd, iov, 3); + return ret; +} + +__rte_format_printf(3, 0) +static int +journal_print(FILE *f __rte_unused, uint32_t level, const char *format, va_list ap) +{ + char *buf = NULL; + int ret, len; + + len = vasprintf(&buf, format, ap); + if (len == 0) + return 0; + + /* check that message ends with newline, if not add one */ + if (buf[len - 1] != '\n') { + char *clone = malloc(len + 1); + if (clone == NULL) { + free(buf); + return 0; + } + + memcpy(clone, buf, len); + clone[len++] = '\n'; + free(buf); + buf = clone; + } + + ret = journal_send(level, buf, len); + free(buf); + return ret; +} + +/* wrapper for log stream to put messages into journal */ +static ssize_t +journal_log_write(__rte_unused void *c, const char *buf, size_t size) +{ + return journal_send(rte_log_cur_msg_loglevel(), buf, size); +} + +static cookie_io_functions_t journal_log_func = { + .write = journal_log_write, +}; + +/* + * Check if stderr is going to system journal. + * This is the documented way to handle systemd journal + * + * See: https://systemd.io/JOURNAL_NATIVE_PROTOCOL/ + * + */ +static bool +using_journal(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 */ +static int +open_journal(const char *id) +{ + char *syslog_id = NULL; + struct sockaddr_un sun = { + .sun_family = AF_UNIX, + .sun_path = "/run/systemd/journal/socket", + }; + ssize_t len; + int s; + + s = socket(AF_UNIX, SOCK_DGRAM, 0); + if (s < 0) + return -1; + + if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0) + goto error; + + /* Send syslog identifier as first message */ + len = asprintf(&syslog_id, "SYSLOG_IDENTIFIER=%s\n", id); + if (len == 0) + goto error; + + if (write(s, syslog_id, len) != len) + goto error; + + free(syslog_id); + + /* redirect other log messages to journal */ + FILE *log_stream = fopencookie(NULL, "w", journal_log_func); + if (log_stream != NULL) + default_log_stream = log_stream; + + return s; + +error: + free(syslog_id); + close(s); + return -1; +} #endif @@ -765,11 +910,24 @@ static cookie_io_functions_t syslog_log_func = { static void log_output_selection(const char *id) { +#ifdef RTE_EXEC_ENV_WINDOWS RTE_SET_USED(id); - -#ifndef RTE_EXEC_ENV_WINDOWS +#else bool is_terminal = isatty(STDERR_FILENO); + /* If stderr is redirected to systemd journal then upgrade */ + if (using_journal()) { + int jfd = open_journal(id); + + if (jfd < 0) { + RTE_LOG_LINE(NOTICE, EAL, "Cannot connect to journal: %s", + strerror(errno)); + } else { + rte_logs.print_func = journal_print; + return; + } + } + if (!(rte_logs.syslog_opt == EAL_LOG_SYSLOG_NONE || (rte_logs.syslog_opt == EAL_LOG_SYSLOG_AUTO && is_terminal))) { int flags = LOG_NDELAY | LOG_PID; -- 2.43.0