File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bmon / src / out_ascii.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 14:58:35 2019 UTC (5 years, 8 months ago) by misho
Branches: bmon, MAIN
CVS tags: v4_0p0, HEAD
bmon ver 4.0

    1: /*
    2:  * out_ascii.c           ASCII Output
    3:  *
    4:  * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
    5:  * Copyright (c) 2013 Red Hat, Inc.
    6:  *
    7:  * Permission is hereby granted, free of charge, to any person obtaining a
    8:  * copy of this software and associated documentation files (the "Software"),
    9:  * to deal in the Software without restriction, including without limitation
   10:  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   11:  * and/or sell copies of the Software, and to permit persons to whom the
   12:  * Software is furnished to do so, subject to the following conditions:
   13:  *
   14:  * The above copyright notice and this permission notice shall be included
   15:  * in all copies or substantial portions of the Software.
   16:  *
   17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   18:  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   22:  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   23:  * DEALINGS IN THE SOFTWARE.
   24:  */
   25: 
   26: #include <bmon/bmon.h>
   27: #include <bmon/conf.h>
   28: #include <bmon/output.h>
   29: #include <bmon/group.h>
   30: #include <bmon/element.h>
   31: #include <bmon/attr.h>
   32: #include <bmon/graph.h>
   33: #include <bmon/history.h>
   34: #include <bmon/utils.h>
   35: 
   36: typedef enum diagram_type_e {
   37: 	D_LIST,
   38: 	D_GRAPH,
   39: 	D_DETAILS
   40: } diagram_type_t;
   41: 
   42: static struct graph_cfg graph_cfg = {
   43: 	.gc_foreground = '*',
   44: 	.gc_background = ' ',
   45: 	.gc_noise = '.',
   46: 	.gc_unknown = '?',
   47: 	.gc_height = 6,
   48: };
   49: 
   50: static diagram_type_t c_diagram_type = D_LIST;
   51: static char *c_hist = "second";
   52: static int c_quit_after = -1;
   53: 
   54: static void print_list(struct element *e)
   55: {
   56: 	char *rxu1 = "", *txu1 = "", *rxu2 = "", *txu2 = "";
   57: 	double rx1 = 0.0f, tx1 = 0.0f, rx2 = 0.0f, tx2 = 0.0f;
   58: 	int rx1prec = 0, tx1prec = 0, rx2prec = 0, tx2prec = 0;
   59: 	char pad[IFNAMSIZ + 32];
   60: 	struct attr *a;
   61: 
   62: 	if (e->e_key_attr[GT_MAJOR] &&
   63: 	    (a = attr_lookup(e, e->e_key_attr[GT_MAJOR]->ad_id)))
   64: 		attr_rate2float(a, &rx1, &rxu1, &rx1prec,
   65: 				   &tx1, &txu1, &tx1prec);
   66: 
   67: 	if (e->e_key_attr[GT_MINOR] &&
   68: 	    (a = attr_lookup(e, e->e_key_attr[GT_MINOR]->ad_id)))
   69: 		attr_rate2float(a, &rx2, &rxu2, &rx2prec,
   70: 				   &tx2, &txu2, &tx2prec);
   71: 
   72: 	memset(pad, 0, sizeof(pad));
   73: 	memset(pad, ' ', e->e_level < 15 ? e->e_level : 15);
   74: 
   75: 	strncat(pad, e->e_name, sizeof(pad) - strlen(pad) - 1);
   76: 
   77: 	if (e->e_description) {
   78: 		strncat(pad, " (", sizeof(pad) - strlen(pad) - 1);
   79: 		strncat(pad, e->e_description, sizeof(pad) - strlen(pad) - 1);
   80: 		strncat(pad, ")", sizeof(pad) - strlen(pad) - 1);
   81: 	}
   82: 
   83: 	printf("  %-36s %8.*f%-3s %8.*f%-3s ",
   84: 	       pad, rx1prec, rx1, rxu1, rx2prec, rx2, rxu2);
   85: 
   86: 	if (e->e_rx_usage == FLT_MAX)
   87: 		printf("   ");
   88: 	else
   89: 		printf("%2.0f%%", e->e_rx_usage);
   90: 
   91: 	printf("  %8.*f%-3s %8.*f%-3s ", tx1prec, tx1, txu1, tx2prec, tx2, txu2);
   92: 
   93: 	if (e->e_tx_usage == FLT_MAX)
   94: 		printf("   \n");
   95: 	else
   96: 		printf("%2.0f%%\n", e->e_tx_usage);
   97: }
   98: 
   99: static void print_attr_detail(struct element *e, struct attr *a, void *arg)
  100: {
  101: 	char *rx_u, *tx_u;
  102: 	int rxprec, txprec;
  103: 
  104: 	double rx = unit_value2str(rate_get_total(&a->a_rx_rate),
  105: 				   a->a_def->ad_unit,
  106: 				   &rx_u, &rxprec);
  107: 	double tx = unit_value2str(rate_get_total(&a->a_tx_rate),
  108: 				   a->a_def->ad_unit,
  109: 				   &tx_u, &txprec);
  110: 
  111: 	printf("  %-36s %12.*f%-3s %12.*f%-3s\n",
  112: 	       a->a_def->ad_description, rxprec, rx, rx_u, txprec, tx, tx_u);
  113: }
  114: 
  115: static void print_details(struct element *e)
  116: {
  117: 	printf(" %s", e->e_name);
  118: 
  119: 	if (e->e_id)
  120: 		printf(" (%u)", e->e_id);
  121: 
  122: 	printf("\n");
  123: 
  124: 	element_foreach_attr(e, print_attr_detail, NULL);
  125: 
  126: 	printf("\n");
  127: }
  128: 
  129: static void print_table(struct graph *g, struct graph_table *tbl, const char *hdr)
  130: {
  131: 	int i;
  132: 
  133: 	if (!tbl->gt_table)
  134: 		return;
  135: 
  136: 	printf("%s   %s\n", hdr, tbl->gt_y_unit);
  137: 
  138: 	for (i = (g->g_cfg.gc_height - 1); i >= 0; i--)
  139: 		printf("%8.2f %s\n", tbl->gt_scale[i],
  140: 		    tbl->gt_table + (i * graph_row_size(&g->g_cfg)));
  141: 	
  142: 	printf("         1   5   10   15   20   25   30   35   40   " \
  143: 		"45   50   55   60\n");
  144: }
  145: 
  146: static void __print_graph(struct element *e, struct attr *a, void *arg)
  147: {
  148: 	struct history *h;
  149: 	struct graph *g;
  150: 
  151: 	if (!(a->a_flags & ATTR_DOING_HISTORY))
  152: 		return;
  153: 
  154: 	graph_cfg.gc_unit = a->a_def->ad_unit;
  155: 
  156: 	list_for_each_entry(h, &a->a_history_list, h_list) {
  157: 		if (strcasecmp(c_hist, h->h_definition->hd_name))
  158: 			continue;
  159: 
  160: 		g = graph_alloc(h, &graph_cfg);
  161: 		graph_refill(g, h);
  162: 
  163: 		printf("Interface: %s\n", e->e_name);
  164: 		printf("Attribute: %s\n", a->a_def->ad_description);
  165: 
  166: 		print_table(g, &g->g_rx, "RX");
  167: 		print_table(g, &g->g_tx, "TX");
  168: 
  169: 		graph_free(g);
  170: 
  171: 	}
  172: }
  173: 
  174: static void print_graph(struct element *e)
  175: {
  176: 	element_foreach_attr(e, __print_graph, NULL);
  177: }
  178: 
  179: static void ascii_draw_element(struct element_group *g, struct element *e,
  180: 			       void *arg)
  181: {
  182: 	switch (c_diagram_type) {
  183: 		case D_LIST:
  184: 			print_list(e);
  185: 			break;
  186: 
  187: 		case D_DETAILS:
  188: 			print_details(e);
  189: 			break;
  190: 
  191: 		case D_GRAPH:
  192: 			print_graph(e);
  193: 			break;
  194: 	}
  195: }
  196: 
  197: static void ascii_draw_group(struct element_group *g, void *arg)
  198: {
  199: 	if (c_diagram_type == D_LIST)
  200: 		printf("%-37s%10s %11s      %%%10s %11s      %%\n",
  201: 		       g->g_hdr->gh_title,
  202: 		       g->g_hdr->gh_column[0],
  203: 		       g->g_hdr->gh_column[1],
  204: 		       g->g_hdr->gh_column[2],
  205: 		       g->g_hdr->gh_column[3]);
  206: 	else
  207: 		printf("%s\n", g->g_hdr->gh_title);
  208: 
  209: 	group_foreach_element(g, ascii_draw_element, NULL);
  210: }
  211: 
  212: static void ascii_draw(void)
  213: {
  214: 	group_foreach(ascii_draw_group, NULL);
  215: 	fflush(stdout);
  216: 
  217: 	if (c_quit_after > 0)
  218: 		if (--c_quit_after == 0)
  219: 			exit(0);
  220: }
  221: 
  222: static void print_help(void)
  223: {
  224: 	printf(
  225: 	"ascii - ASCII Output\n" \
  226: 	"\n" \
  227: 	"  Plain configurable ASCII output.\n" \
  228: 	"\n" \
  229: 	"  scriptable: (output graph for eth1 10 times)\n" \
  230: 	"      bmon -p eth1 -o 'ascii:diagram=graph;quitafter=10'\n" \
  231: 	"  show details for all ethernet interfaces:\n" \
  232: 	"      bmon -p 'eth*' -o 'ascii:diagram=details;quitafter=1'\n" \
  233: 	"\n" \
  234: 	"  Author: Thomas Graf <tgraf@suug.ch>\n" \
  235: 	"\n" \
  236: 	"  Options:\n" \
  237: 	"    diagram=TYPE   Diagram type\n" \
  238: 	"    fgchar=CHAR    Foreground character (default: '*')\n" \
  239: 	"    bgchar=CHAR    Background character (default: '.')\n" \
  240: 	"    nchar=CHAR     Noise character (default: ':')\n" \
  241: 	"    uchar=CHAR     Unknown character (default: '?')\n" \
  242: 	"    height=NUM     Height of graph (default: 6)\n" \
  243: 	"    xunit=UNIT     X-Axis Unit (default: seconds)\n" \
  244: 	"    yunit=UNIT     Y-Axis Unit (default: dynamic)\n" \
  245: 	"    quitafter=NUM  Quit bmon after NUM outputs\n");
  246: }
  247: 
  248: static void ascii_parse_opt(const char *type, const char *value)
  249: {
  250: 	if (!strcasecmp(type, "diagram") && value) {
  251: 		if (tolower(*value) == 'l')
  252: 			c_diagram_type = D_LIST;
  253: 		else if (tolower(*value) == 'g')
  254: 			c_diagram_type = D_GRAPH;
  255: 		else if (tolower(*value) == 'd')
  256: 			c_diagram_type = D_DETAILS;
  257: 		else
  258: 			quit("Unknown diagram type '%s'\n", value);
  259: 	} else if (!strcasecmp(type, "fgchar") && value)
  260: 		graph_cfg.gc_foreground = value[0];
  261: 	else if (!strcasecmp(type, "bgchar") && value)
  262: 		graph_cfg.gc_background = value[0];
  263: 	else if (!strcasecmp(type, "nchar") && value)
  264: 		graph_cfg.gc_noise = value[0];
  265: #if 0
  266: 	else if (!strcasecmp(type, "uchar") && value)
  267: 		set_unk_char(value[0]);
  268: #endif
  269: 	else if (!strcasecmp(type, "xunit") && value)
  270: 		c_hist = strdup(value);
  271: #if 0
  272: 	else if (!strcasecmp(type, "yunit") && value) {
  273: 		struct unit *u;
  274: 
  275: 		if (!(u = unit_lookup(value)))
  276: 			quit("Unknown unit '%s'\n", value);
  277: 
  278: 		graph_cfg.gc_unit = u;
  279: #endif
  280: 	else if (!strcasecmp(type, "height") && value)
  281: 		graph_cfg.gc_height = strtol(value, NULL, 0);
  282: 	else if (!strcasecmp(type, "quitafter") && value)
  283: 		c_quit_after = strtol(value, NULL, 0);
  284: 	else if (!strcasecmp(type, "help")) {
  285: 		print_help();
  286: 		exit(0);
  287: 	} else
  288: 		quit("Unknown module option '%s'\n", type);
  289: }
  290: 
  291: static struct bmon_module ascii_ops = {
  292: 	.m_name		= "ascii",
  293: 	.m_do		= ascii_draw,
  294: 	.m_parse_opt	= ascii_parse_opt,
  295: };
  296: 
  297: static void __init ascii_init(void)
  298: {
  299: 	output_register(&ascii_ops);
  300: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>