vty: Add a 'skip-zero' version of 'show stats' and 'show rate-counters'

In many cases, a lot of the counters are zero, and we're likely
not interested in those, but only the non-zero counters.  Add a version
of the 'show stats' command which dumps only those items with a non-zero
total value.

Change-Id: Ie4df1c139e3c82deca1dd3cdab5d3909e0513684
This commit is contained in:
Harald Welte 2022-04-18 11:39:08 +02:00 committed by laforge
parent be5e838dbb
commit 3b007f86ac
3 changed files with 102 additions and 34 deletions

View File

@ -14,15 +14,23 @@ char *vty_cmd_string_from_valstr(void *ctx, const struct value_string *vals,
void vty_out_rate_ctr_group(struct vty *vty, const char *prefix, void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
struct rate_ctr_group *ctrg); struct rate_ctr_group *ctrg);
void vty_out_rate_ctr_group2(struct vty *vty, const char *prefix,
struct rate_ctr_group *ctrg, bool skip_zero);
void vty_out_rate_ctr_group_fmt(struct vty *vty, const char *fmt, void vty_out_rate_ctr_group_fmt(struct vty *vty, const char *fmt,
struct rate_ctr_group *ctrg); struct rate_ctr_group *ctrg);
void vty_out_rate_ctr_group_fmt2(struct vty *vty, const char *fmt,
struct rate_ctr_group *ctrg, bool skip_zero);
void vty_out_stat_item_group(struct vty *vty, const char *prefix, void vty_out_stat_item_group(struct vty *vty, const char *prefix,
struct osmo_stat_item_group *statg); struct osmo_stat_item_group *statg);
void vty_out_stat_item_group2(struct vty *vty, const char *prefix,
struct osmo_stat_item_group *statg, bool skip_zero);
void vty_out_statistics_full(struct vty *vty, const char *prefix); void vty_out_statistics_full(struct vty *vty, const char *prefix);
void vty_out_statistics_partial(struct vty *vty, const char *prefix, void vty_out_statistics_full2(struct vty *vty, const char *prefix, bool skip_zero);
int max_level); void vty_out_statistics_partial(struct vty *vty, const char *prefix, int max_level);
void vty_out_statistics_partial2(struct vty *vty, const char *prefix, int max_level, bool skip_zero);
struct osmo_fsm; struct osmo_fsm;

View File

@ -1,5 +1,5 @@
/* /*
* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> * (C) 2009-2022 by Harald Welte <laforge@gnumonks.org>
* (C) 2009-2014 by Holger Hans Peter Freyther * (C) 2009-2014 by Holger Hans Peter Freyther
* (C) 2015 by sysmocom - s.f.m.c. GmbH * (C) 2015 by sysmocom - s.f.m.c. GmbH
* All Rights Reserved * All Rights Reserved
@ -39,6 +39,7 @@
#define CFG_REPORTER_STR "Configure a stats reporter\n" #define CFG_REPORTER_STR "Configure a stats reporter\n"
#define SHOW_STATS_STR "Show statistical values\n" #define SHOW_STATS_STR "Show statistical values\n"
#define SKIP_ZERO_STR "Skip items with total count zero\n"
#define STATS_STR "Stats related commands\n" #define STATS_STR "Stats related commands\n"
@ -418,25 +419,32 @@ DEFUN(cfg_tcp_stats_batch_size, cfg_tcp_stats_batch_size_cmd,
DEFUN(show_stats, DEFUN(show_stats,
show_stats_cmd, show_stats_cmd,
"show stats", "show stats [skip-zero]",
SHOW_STR SHOW_STATS_STR) SHOW_STR SHOW_STATS_STR SKIP_ZERO_STR)
{ {
vty_out_statistics_full(vty, ""); bool skip_zero = false;
if (argc > 0)
skip_zero = true;
vty_out_statistics_full2(vty, "", skip_zero);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(show_stats_level, DEFUN(show_stats_level,
show_stats_level_cmd, show_stats_level_cmd,
"show stats level (global|peer|subscriber)", "show stats level (global|peer|subscriber) [skip-zero]",
SHOW_STR SHOW_STATS_STR SHOW_STR SHOW_STATS_STR
"Set the maximum group level\n" "Set the maximum group level\n"
"Show global groups only\n" "Show global groups only\n"
"Show global and network peer related groups\n" "Show global and network peer related groups\n"
"Show global, peer, and subscriber groups\n") "Show global, peer, and subscriber groups\n" SKIP_ZERO_STR)
{ {
int level = get_string_value(stats_class_strs, argv[0]); int level = get_string_value(stats_class_strs, argv[0]);
vty_out_statistics_partial(vty, "", level); bool skip_zero = false;
if (argc > 1)
skip_zero = true;
vty_out_statistics_partial2(vty, "", level, skip_zero);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -599,23 +607,32 @@ DEFUN(show_stats_asciidoc_table,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
struct rctr_vty_ctx {
struct vty *vty;
bool skip_zero;
};
static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_) static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
{ {
struct vty *vty = sctx_; struct rctr_vty_ctx *sctx = sctx_;
struct vty *vty = sctx->vty;
vty_out(vty, "%s %u", ctrg->desc->group_description, ctrg->idx); vty_out(vty, "%s %u", ctrg->desc->group_description, ctrg->idx);
if (ctrg->name != NULL) if (ctrg->name != NULL)
vty_out(vty, " (%s)", ctrg->name); vty_out(vty, " (%s)", ctrg->name);
vty_out(vty, ":%s", VTY_NEWLINE); vty_out(vty, ":%s", VTY_NEWLINE);
vty_out_rate_ctr_group_fmt(vty, "%25n: %10c (%S/s %M/m %H/h %D/d) %d", ctrg); vty_out_rate_ctr_group_fmt2(vty, "%25n: %10c (%S/s %M/m %H/h %D/d) %d", ctrg, sctx->skip_zero);
return 0; return 0;
} }
DEFUN(show_rate_counters, DEFUN(show_rate_counters,
show_rate_counters_cmd, show_rate_counters_cmd,
"show rate-counters", "show rate-counters [skip-zero]",
SHOW_STR "Show all rate counters\n") SHOW_STR "Show all rate counters\n" SKIP_ZERO_STR)
{ {
rate_ctr_for_each_group(rate_ctr_group_handler, vty); struct rctr_vty_ctx rctx = { .vty = vty, .skip_zero = false };
if (argc > 0)
rctx.skip_zero = true;
rate_ctr_for_each_group(rate_ctr_group_handler, &rctx);
return CMD_SUCCESS; return CMD_SUCCESS;
} }

View File

@ -21,6 +21,7 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@ -44,6 +45,7 @@ struct vty_out_context {
struct vty *vty; struct vty *vty;
const char *prefix; const char *prefix;
int max_level; int max_level;
bool skip_zero;
}; };
static int rate_ctr_handler( static int rate_ctr_handler(
@ -53,6 +55,9 @@ static int rate_ctr_handler(
struct vty_out_context *vctx = vctx_; struct vty_out_context *vctx = vctx_;
struct vty *vty = vctx->vty; struct vty *vty = vctx->vty;
if (vctx->skip_zero && ctr->current == 0)
return 0;
vty_out(vty, " %s%s: %8" PRIu64 " " vty_out(vty, " %s%s: %8" PRIu64 " "
"(%" PRIu64 "/s %" PRIu64 "/m %" PRIu64 "/h %" PRIu64 "/d)%s", "(%" PRIu64 "/s %" PRIu64 "/m %" PRIu64 "/h %" PRIu64 "/d)%s",
vctx->prefix, desc->description, ctr->current, vctx->prefix, desc->description, ctr->current,
@ -69,17 +74,24 @@ static int rate_ctr_handler(
* \param[in] vty The VTY to which it should be printed * \param[in] vty The VTY to which it should be printed
* \param[in] prefix Any additional log prefix ahead of each line * \param[in] prefix Any additional log prefix ahead of each line
* \param[in] ctrg Rate counter group to be printed * \param[in] ctrg Rate counter group to be printed
* \param[in] skip_zero Skip all zero-valued counters
*/ */
void vty_out_rate_ctr_group(struct vty *vty, const char *prefix, void vty_out_rate_ctr_group2(struct vty *vty, const char *prefix,
struct rate_ctr_group *ctrg) struct rate_ctr_group *ctrg, bool skip_zero)
{ {
struct vty_out_context vctx = {vty, prefix}; struct vty_out_context vctx = {vty, prefix, 0, skip_zero};
vty_out(vty, "%s%s:%s", prefix, ctrg->desc->group_description, VTY_NEWLINE); vty_out(vty, "%s%s:%s", prefix, ctrg->desc->group_description, VTY_NEWLINE);
rate_ctr_for_each_counter(ctrg, rate_ctr_handler, &vctx); rate_ctr_for_each_counter(ctrg, rate_ctr_handler, &vctx);
} }
void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
struct rate_ctr_group *ctrg)
{
vty_out_rate_ctr_group2(vty, prefix, ctrg, false);
}
static char * static char *
pad_append_str(char *s, const char *a, int minwidth) pad_append_str(char *s, const char *a, int minwidth)
{ {
@ -103,7 +115,12 @@ static int rate_ctr_handler_fmt(
struct vty_out_context *vctx = vctx_; struct vty_out_context *vctx = vctx_;
struct vty *vty = vctx->vty; struct vty *vty = vctx->vty;
const char *fmt = vctx->prefix; const char *fmt = vctx->prefix;
char *s = talloc_strdup(vty, ""); char *s;
if (vctx->skip_zero && ctr->current == 0)
return 0;
s = talloc_strdup(vty, "");
OSMO_ASSERT(s); OSMO_ASSERT(s);
while (*fmt) { while (*fmt) {
@ -205,14 +222,20 @@ static int rate_ctr_handler_fmt(
* \param[in] vty The VTY to which it should be printed * \param[in] vty The VTY to which it should be printed
* \param[in] ctrg Rate counter group to be printed * \param[in] ctrg Rate counter group to be printed
* \param[in] fmt A format which may contain the above directives. * \param[in] fmt A format which may contain the above directives.
* \param[in] skip_zero Skip all zero-valued counters
*/ */
void vty_out_rate_ctr_group_fmt(struct vty *vty, const char *fmt, void vty_out_rate_ctr_group_fmt2(struct vty *vty, const char *fmt,
struct rate_ctr_group *ctrg) struct rate_ctr_group *ctrg, bool skip_zero)
{ {
struct vty_out_context vctx = {vty, fmt}; struct vty_out_context vctx = {vty, fmt, 0, skip_zero};
rate_ctr_for_each_counter(ctrg, rate_ctr_handler_fmt, &vctx); rate_ctr_for_each_counter(ctrg, rate_ctr_handler_fmt, &vctx);
} }
void vty_out_rate_ctr_group_fmt(struct vty *vty, const char *fmt,
struct rate_ctr_group *ctrg)
{
vty_out_rate_ctr_group_fmt2(vty, fmt, ctrg, false);
}
static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *vctx_) static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *vctx_)
{ {
struct vty_out_context *vctx = vctx_; struct vty_out_context *vctx = vctx_;
@ -244,12 +267,14 @@ static int osmo_stat_item_handler(
struct vty_out_context *vctx = vctx_; struct vty_out_context *vctx = vctx_;
struct vty *vty = vctx->vty; struct vty *vty = vctx->vty;
const struct osmo_stat_item_desc *desc = osmo_stat_item_get_desc(item); const struct osmo_stat_item_desc *desc = osmo_stat_item_get_desc(item);
int32_t value = osmo_stat_item_get_last(item);
const char *unit = (desc->unit != OSMO_STAT_ITEM_NO_UNIT) ? desc->unit : ""; const char *unit = (desc->unit != OSMO_STAT_ITEM_NO_UNIT) ? desc->unit : "";
if (vctx->skip_zero && value == 0)
return 0;
vty_out(vty, " %s%s: %8" PRIi32 " %s%s", vty_out(vty, " %s%s: %8" PRIi32 " %s%s",
vctx->prefix, desc->description, vctx->prefix, desc->description, value, unit, VTY_NEWLINE);
osmo_stat_item_get_last(item),
unit, VTY_NEWLINE);
return 0; return 0;
} }
@ -258,17 +283,24 @@ static int osmo_stat_item_handler(
* \param[in] vty The VTY to which it should be printed * \param[in] vty The VTY to which it should be printed
* \param[in] prefix Any additional log prefix ahead of each line * \param[in] prefix Any additional log prefix ahead of each line
* \param[in] statg Stat item group to be printed * \param[in] statg Stat item group to be printed
* \param[in] skip_zero Skip all zero-valued counters
*/ */
void vty_out_stat_item_group(struct vty *vty, const char *prefix, void vty_out_stat_item_group2(struct vty *vty, const char *prefix,
struct osmo_stat_item_group *statg) struct osmo_stat_item_group *statg, bool skip_zero)
{ {
struct vty_out_context vctx = {vty, prefix}; struct vty_out_context vctx = {vty, prefix, 0, skip_zero};
vty_out(vty, "%s%s:%s", prefix, statg->desc->group_description, vty_out(vty, "%s%s:%s", prefix, statg->desc->group_description,
VTY_NEWLINE); VTY_NEWLINE);
osmo_stat_item_for_each_item(statg, osmo_stat_item_handler, &vctx); osmo_stat_item_for_each_item(statg, osmo_stat_item_handler, &vctx);
} }
void vty_out_stat_item_group(struct vty *vty, const char *prefix,
struct osmo_stat_item_group *statg)
{
return vty_out_stat_item_group2(vty, prefix, statg, false);
}
static int osmo_stat_item_group_handler(struct osmo_stat_item_group *statg, void *vctx_) static int osmo_stat_item_group_handler(struct osmo_stat_item_group *statg, void *vctx_)
{ {
struct vty_out_context *vctx = vctx_; struct vty_out_context *vctx = vctx_;
@ -298,21 +330,22 @@ static int handle_counter(struct osmo_counter *counter, void *vctx_)
struct vty_out_context *vctx = vctx_; struct vty_out_context *vctx = vctx_;
struct vty *vty = vctx->vty; struct vty *vty = vctx->vty;
const char *description = counter->description; const char *description = counter->description;
unsigned long value = osmo_counter_get(counter);
if (vctx->skip_zero && value == 0)
return 0;
if (!counter->description) if (!counter->description)
description = counter->name; description = counter->name;
vty_out(vty, " %s%s: %8lu%s", vty_out(vty, " %s%s: %8lu%s", vctx->prefix, description, value, VTY_NEWLINE);
vctx->prefix, description,
osmo_counter_get(counter), VTY_NEWLINE);
return 0; return 0;
} }
void vty_out_statistics_partial(struct vty *vty, const char *prefix, void vty_out_statistics_partial2(struct vty *vty, const char *prefix, int max_level, bool skip_zero)
int max_level)
{ {
struct vty_out_context vctx = {vty, prefix, max_level}; struct vty_out_context vctx = {vty, prefix, max_level, skip_zero};
vty_out(vty, "%sUngrouped counters:%s", prefix, VTY_NEWLINE); vty_out(vty, "%sUngrouped counters:%s", prefix, VTY_NEWLINE);
osmo_counters_for_each(handle_counter, &vctx); osmo_counters_for_each(handle_counter, &vctx);
@ -320,9 +353,19 @@ void vty_out_statistics_partial(struct vty *vty, const char *prefix,
osmo_stat_item_for_each_group(osmo_stat_item_group_handler, &vctx); osmo_stat_item_for_each_group(osmo_stat_item_group_handler, &vctx);
} }
void vty_out_statistics_partial(struct vty *vty, const char *prefix, int max_level)
{
return vty_out_statistics_partial2(vty, prefix, max_level, false);
}
void vty_out_statistics_full2(struct vty *vty, const char *prefix, bool skip_zero)
{
vty_out_statistics_partial2(vty, prefix, INT_MAX, skip_zero);
}
void vty_out_statistics_full(struct vty *vty, const char *prefix) void vty_out_statistics_full(struct vty *vty, const char *prefix)
{ {
vty_out_statistics_partial(vty, prefix, INT_MAX); vty_out_statistics_full2(vty, prefix, false);
} }
/*! Generate a VTY command string from value_string */ /*! Generate a VTY command string from value_string */