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 D272043D17; Thu, 21 Mar 2024 17:18:11 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B7B2B42DC3; Thu, 21 Mar 2024 17:18:11 +0100 (CET) Received: from mail-il1-f175.google.com (mail-il1-f175.google.com [209.85.166.175]) by mails.dpdk.org (Postfix) with ESMTP id C320B427E1 for ; Thu, 21 Mar 2024 17:18:10 +0100 (CET) Received: by mail-il1-f175.google.com with SMTP id e9e14a558f8ab-3667770b8e8so5259695ab.0 for ; Thu, 21 Mar 2024 09:18:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1711037890; x=1711642690; 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=hqeA3Z23W4oIs9rPBGRyEAa5ziQrrAlyT6cOMR/IRh4=; b=xmB3WlkZHTRcBiP0UGDeGDCER4s5eXYuwiXL3A7KLqBQHRbWRMhbkwLaFbBgQKHJsH QOv3ftSohVP8ibj/RhfD4Y58Cz04hnRtHMO1dWjGkaDFmxbz/wgxtck+iRFcIzlp0sz7 hIZT4CfSTnKZ3azcCY0p6s3OlI7HBLuEy90bslNRPmTDHsOgZcI616BQBdqf2zcSiJhn odVjCNaGfB4FLkeKZgD8exJCUhy+xX4HrUzDbNswBCKc8RVZy8Mqd9icaquwowewE7On HBOUIDLV+kYd5OxhSRkz/I8ibEheLjlDkjPVYGYeZUXgVKcyG2XsZcdirI2pMA7hm9c4 DGMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711037890; x=1711642690; 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=hqeA3Z23W4oIs9rPBGRyEAa5ziQrrAlyT6cOMR/IRh4=; b=QaHiJukyODUoPx4Ip9dkxsCqvptG4ob3AfbFvmR/gSViCtv0ILTbfrSHYA0EvMPboI GfXo0opxHQCUOPDBpMibvt1Xp8WiAU5boOTgOyuajsBIJ2YtLclIFsksXARVPFk+cRMn ex39BeLPFeM1v0wsNpwZtqpoH+qS5Cz0rVToMhF0UR/uynGSoMOTaAu9+eIdr0ToyRa+ xmyY8QRnH/mc3INrTnWjbH5SAUT9lUrAidajNXH9KlL8ApVzVgt/1ZUNbMMA1d9DPOpf SlF26Mh0j8YDHpwtjoqQp6ZUYMNFDFiagr8l8bdhmq3JRivFaoPkybBawINcwxKA7SJg uE+Q== X-Gm-Message-State: AOJu0YxsK2re/WukUaNT/nzlkQ6vUuGHsIQnGrjUizLzel54p/a9DUke dUna33MMLZms8yKU2sJQiPM8b28XHM8fb1s/155wnXhgE7Dvb9qIL6a1eDNZqt1qG/U3UZvD9FP 7 X-Google-Smtp-Source: AGHT+IGHtaDJDZ0pm0a43uDe66akgR1s1xQHZZt8UiuJygLdpGIKY5Gm6hGwU1pKxIViFnHerwWzfQ== X-Received: by 2002:a05:6a20:dda4:b0:1a3:3c9b:182 with SMTP id kw36-20020a056a20dda400b001a33c9b0182mr5368109pzb.57.1711037523643; Thu, 21 Mar 2024 09:12:03 -0700 (PDT) Received: from hermes.local (204-195-123-203.wavecable.com. [204.195.123.203]) by smtp.gmail.com with ESMTPSA id w62-20020a638241000000b005e485fbd455sm41815pgd.45.2024.03.21.09.12.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Mar 2024 09:12:03 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger Subject: [PATCH v10 09/10] log: colorize log output Date: Thu, 21 Mar 2024 09:00:25 -0700 Message-ID: <20240321161146.340421-10-stephen@networkplumber.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240321161146.340421-1-stephen@networkplumber.org> References: <20200814173441.23086-1-stephen@networkplumber.org> <20240321161146.340421-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 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. Signed-off-by: Stephen Hemminger --- lib/eal/common/eal_common_options.c | 10 +++ lib/eal/common/eal_options.h | 2 + lib/log/log_internal.h | 5 ++ lib/log/log_unix.c | 132 +++++++++++++++++++++++++--- lib/log/log_windows.c | 6 ++ lib/log/version.map | 1 + 6 files changed, 146 insertions(+), 10 deletions(-) diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c index 4e2c3d0f255c..522634f1dcfa 100644 --- a/lib/eal/common/eal_common_options.c +++ b/lib/eal/common/eal_common_options.c @@ -78,6 +78,7 @@ eal_long_options[] = { {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_LOG_COLOR, 1, NULL, OPT_LOG_COLOR_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 }, @@ -1910,6 +1911,15 @@ 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; + case OPT_TRACE_NUM: { if (eal_trace_args_save(optarg) < 0) { EAL_LOG(ERR, "invalid parameters for --" diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h index e24c9eca53ca..5a63c1dd3a32 100644 --- a/lib/eal/common/eal_options.h +++ b/lib/eal/common/eal_options.h @@ -37,6 +37,8 @@ enum { OPT_LOG_LEVEL_NUM, #define OPT_LOG_TIMESTAMP "log-timestamp" OPT_LOG_TIMESTAMP_NUM, +#define OPT_LOG_COLOR "log-color" + OPT_LOG_COLOR_NUM, #define OPT_TRACE "trace" OPT_TRACE_NUM, #define OPT_TRACE_DIR "trace-dir" diff --git a/lib/log/log_internal.h b/lib/log/log_internal.h index 0e18d147cf98..b90c668f4668 100644 --- a/lib/log/log_internal.h +++ b/lib/log/log_internal.h @@ -52,5 +52,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 */ diff --git a/lib/log/log_unix.c b/lib/log/log_unix.c index cb8f17bc83ef..1af93795fec5 100644 --- a/lib/log/log_unix.c +++ b/lib/log/log_unix.c @@ -11,6 +11,7 @@ #include #include +#include #include #include "log_internal.h" @@ -24,15 +25,113 @@ enum eal_log_time_format { EAL_LOG_TIMESTAMP_ISO, }; +enum eal_log_color { + EAL_LOG_COLOR_AUTO = 0, /* default */ + EAL_LOG_COLOR_NEVER, + EAL_LOG_COLOR_ALWAYS, +}; + static struct { + enum eal_log_color color_mode; enum eal_log_time_format time_format; + bool show_color; struct timespec start_time; struct timespec last_time; struct tm last_tm; } log = { + .color_mode = EAL_LOG_COLOR_AUTO, .time_format = EAL_LOG_TIMESTAMP_NONE, }; +enum color { + COLOR_NONE, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW, + COLOR_BLUE, + COLOR_MAGENTA, + COLOR_CYAN, + COLOR_WHITE, + COLOR_BOLD, + COLOR_CLEAR +}; + +static const char * const color_code[] = { + [COLOR_NONE] = "", + [COLOR_RED] = "\e[31m", + [COLOR_GREEN] = "\e[32m", + [COLOR_YELLOW] = "\e[33m", + [COLOR_BLUE] = "\e[34m", + [COLOR_MAGENTA] = "\e[35m", + [COLOR_CYAN] = "\e[36m", + [COLOR_WHITE] = "\e[37m", + [COLOR_BOLD] = "\e[1m", + [COLOR_CLEAR] = "\e[0m", +}; + +__rte_format_printf(3, 4) +static int color_fprintf(FILE *out, enum color color, const char *fmt, ...) +{ + va_list args; + int ret = 0; + + va_start(args, fmt); + ret = fprintf(out, "%s", color_code[color]); + ret += vfprintf(out, fmt, args); + ret += fprintf(out, "%s", color_code[COLOR_CLEAR]); + + return ret; +} + +static ssize_t +color_log_write(FILE *f, int level, const char *msg, size_t size) +{ + size_t i; + ssize_t ret = 0; + + /* find first : delimiter in message */ + for (i = 0; i < size; i++) { + if (msg[i] == ':') { + ++i; /* put colon in the color */ + ret = color_fprintf(stderr, COLOR_YELLOW, "%.*s", (int)i, msg); + msg += i; + size -= i; + break; + } + } + + if (level <= 0 || level >= (int)RTE_LOG_INFO) + ret += fprintf(f, "%.*s", (int)size, msg); + else if (level >= (int)RTE_LOG_ERR) + ret += color_fprintf(f, COLOR_BOLD, "%.*s", (int)size, msg); + else + ret += color_fprintf(f, COLOR_RED, "%.*s", (int)size, msg); + + return ret; +} + +/* + * Controls whether color is enabled: + * modes are: + * always - enable color output regardless + * auto - enable if stderr is a terminal + * never - color output is disabled. + */ +int +eal_log_color(const char *mode) +{ + if (mode == NULL || strcmp(mode, "always") == 0) + log.color_mode = EAL_LOG_COLOR_ALWAYS; + else if (strcmp(mode, "never") == 0) + log.color_mode = EAL_LOG_COLOR_NEVER; + else if (strcmp(mode, "auto") == 0) + log.color_mode = EAL_LOG_COLOR_AUTO; + else + return -1; + + return 0; +} + int eal_log_timestamp(const char *str) { @@ -153,18 +252,28 @@ console_log_timestamp(char *tsbuf, size_t tsbuflen) static ssize_t console_log_write(__rte_unused void *c, const char *msg, size_t size) { - char buf[128]; + int level = rte_log_cur_msg_loglevel(); + char tsbuf[128] = ""; ssize_t ret; - ret = console_log_timestamp(buf, sizeof(buf)); - if (ret == 0) - ret = fwrite(msg, 1, size, stderr); - else - ret = fprintf(stderr, "[%s] %.*s", buf, (int)size, msg); + ret = console_log_timestamp(tsbuf, sizeof(tsbuf)); + if (ret == 0) { + if (log.show_color) + ret = color_log_write(stderr, level, msg, size); + else + ret = fwrite(msg, 1, size, stderr); + } else { + if (log.show_color) { + color_fprintf(stderr, COLOR_GREEN, "[%s] ", tsbuf); + ret = color_log_write(stderr, level, msg, size); + } else { + ret = fprintf(stderr, "[%s] %.*s", tsbuf, (int)size, msg); + } + } fflush(stderr); /* Syslog error levels are from 0 to 7, so subtract 1 to convert */ - syslog(rte_log_cur_msg_loglevel() - 1, "%.*s", (int)size, msg); + syslog(level - 1, "%.*s", (int)size, msg); return ret; } @@ -190,13 +299,16 @@ eal_log_init(const char *id, int facility) { FILE *log_stream; - clock_gettime(CLOCK_MONOTONIC, &log.start_time); - log.last_time = log.start_time; - /* skip if user has already setup a log stream */ if (eal_log_get_default()) return 0; + log.show_color = (log.color_mode == EAL_LOG_COLOR_ALWAYS) || + (log.color_mode == EAL_LOG_COLOR_AUTO && isatty(STDERR_FILENO)); + + clock_gettime(CLOCK_MONOTONIC, &log.start_time); + log.last_time = log.start_time; + log_stream = fopencookie(NULL, "w+", console_log_func); if (log_stream == NULL) return -1; diff --git a/lib/log/log_windows.c b/lib/log/log_windows.c index 8aa68a181bec..1cb72f519a91 100644 --- a/lib/log/log_windows.c +++ b/lib/log/log_windows.c @@ -12,6 +12,12 @@ eal_log_timestamp(__rte_unused const char *fmt) return -1; /* not implemented */ } +int +eal_log_color(__rte_unused const char *mode) +{ + return -1; /* not implemented */ +} + /* set the log to default function, called during eal init process. */ int eal_log_init(__rte_unused const char *id, __rte_unused int facility) diff --git a/lib/log/version.map b/lib/log/version.map index 697cdb3cb1b2..1fe6955427b7 100644 --- a/lib/log/version.map +++ b/lib/log/version.map @@ -25,6 +25,7 @@ DPDK_24 { INTERNAL { global: + eal_log_color; eal_log_get_default; eal_log_init; eal_log_level2str; -- 2.43.0