zpcimon: Allow setting output format and use JSON Lines in systemd unit

Introduce separate '--format' option to set output format. Use the new
JSON Lines format explicitly in the systemd unit. Since JSON Lines
format only uses printable characters this removes the need for passing
'-a' to systemctl status. At the same time JSON-SEQ is more easily
parsable using 'jq --seq' so keep it the default for easier scripting.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Niklas Schnelle
2026-06-17 21:48:47 +02:00
committed by Jan Höppner
parent 8a4a4e0557
commit 2c63c69af4
4 changed files with 59 additions and 3 deletions

View File

@@ -13,7 +13,7 @@ Description=Monitor health of directly attached PCI NIC optical modules
[Service]
Type=exec
ExecStart=@usrsbin_path@/zpcimon --send-report --monitor --interval 86400
ExecStart=@usrsbin_path@/zpcimon --send-report --monitor --format jsonl --interval 86400
KillMode=control-group
[Install]

View File

@@ -84,6 +84,14 @@ on".
.PP
.PP
.
.SS Output Format Options
.OD format "" <FORMAT>
Set the output format out of json, json-seq, jsonl, pairs, and csv. Note that
only json-seq and jsonl sequence formats are supported for monitoring mode as
they handle a continuous stream of updates well. While they are not supported
in query mode.
.PP
.
.SS General Options
.OD help "h" ""
Print usage information, then exit.

View File

@@ -40,6 +40,8 @@ struct options {
bool report;
bool module_info;
bool quiet;
enum util_fmt_t format;
bool explicit_format;
uint32_t interval_seconds;
};
@@ -63,6 +65,7 @@ static const struct util_prg prg = {
static void parse_cmdline(int argc, char *argv[], struct options *opts)
{
enum util_fmt_t fmt;
uint32_t seconds;
int cmd, ret;
@@ -85,6 +88,12 @@ static void parse_cmdline(int argc, char *argv[], struct options *opts)
case OPT_DUMP:
opts->module_info = true;
break;
case OPT_FORMAT:
if (!util_fmt_name_to_type(optarg, &fmt))
errx(EXIT_FAILURE, "Unknown format %s", optarg);
opts->format = fmt;
opts->explicit_format = true;
break;
case 'i':
ret = sscanf(optarg, "%u", &seconds);
if (ret != 1) {
@@ -224,7 +233,7 @@ static void dump_all_adapter_data(struct opticsmon_ctx *ctx)
static int oneshot_mode(struct opticsmon_ctx *ctx)
{
util_fmt_init(stdout, FMT_JSON, FMT_DEFAULT, API_LEVEL);
util_fmt_init(stdout, ctx->opts.format, FMT_DEFAULT, API_LEVEL);
if (!ctx->opts.quiet)
util_fmt_obj_start(FMT_LIST, "adapters");
dump_all_adapter_data(ctx);
@@ -375,7 +384,7 @@ static int monitor_mode(struct opticsmon_ctx *ctx)
goto close_timerfd;
}
util_fmt_init(stdout, FMT_JSONSEQ, FMT_DEFAULT, API_LEVEL);
util_fmt_init(stdout, ctx->opts.format, FMT_DEFAULT, API_LEVEL);
ret = link_mon_nl_waitfd_create(&ctx->lctx, on_link_change, ctx);
if (ret) {
fprintf(stderr, "Failed to create link monitoring socket\n");
@@ -393,12 +402,42 @@ close_timerfd:
return ret;
}
static bool is_supported_fmt(enum util_fmt_t fmt, bool monitor)
{
switch (fmt) {
case FMT_JSON:
case FMT_PAIRS:
return monitor ? false : true;
case FMT_JSONL:
case FMT_JSONSEQ:
return monitor ? true : false;
default:
return false;
}
}
static int set_format(struct options *opts)
{
if (!opts->explicit_format)
opts->format = (opts->monitor) ? FMT_JSONSEQ : FMT_JSON;
if (!is_supported_fmt(opts->format, opts->monitor)) {
warnx("Format %s is not supported in %s mode",
util_fmt_type_to_name(opts->format), (opts->monitor) ? "monitor" : "query");
return -EINVAL;
}
return 0;
}
int main(int argc, char **argv)
{
struct opticsmon_ctx ctx = { .opts = { .interval_seconds = 86400 } };
int ret;
parse_cmdline(argc, argv, &ctx.opts);
ret = set_format(&ctx.opts);
if (ret)
return ret;
ret = ethtool_nl_connect(&ctx.ethtool_ctx);
if (ret)
return ret;

View File

@@ -7,9 +7,11 @@
#ifndef OPTICSMON_CLI_H
#define OPTICSMON_CLI_H
#include "lib/util_fmt.h"
#include "lib/util_opt.h"
#define OPT_DUMP 128
#define OPT_FORMAT 129
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPERATION OPTIONS"),
@@ -41,6 +43,13 @@ static struct util_opt opt_vec[] = {
"in the absence of link state changes. A value larger than "
"24 hours (86400 seconds) is clamped down to 24 hours.",
},
UTIL_OPT_SECTION("OUTPUT FORMAT OPTIONS"),
{
.option = { "format", required_argument, NULL, OPT_FORMAT },
.argument = "FORMAT",
.flags = UTIL_OPT_FLAG_NOSHORT,
.desc = "Output format (" FMT_TYPE_NAMES ")",
},
UTIL_OPT_SECTION("GENERAL OPTIONS"),
UTIL_OPT_HELP,
UTIL_OPT_VERSION,