File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bmon / src / out_ascii.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:19:56 2012 UTC (12 years, 4 months ago) by misho
Branches: bmon, MAIN
CVS tags: v2_1_0p0, v2_1_0, HEAD
bmon

    1: /*
    2:  * out_ascii.c           ASCII Output
    3:  *
    4:  * Copyright (c) 2001-2005 Thomas Graf <tgraf@suug.ch>
    5:  *
    6:  * Permission is hereby granted, free of charge, to any person obtaining a
    7:  * copy of this software and associated documentation files (the "Software"),
    8:  * to deal in the Software without restriction, including without limitation
    9:  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   10:  * and/or sell copies of the Software, and to permit persons to whom the
   11:  * Software is furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included
   14:  * in all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   17:  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   21:  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   22:  * DEALINGS IN THE SOFTWARE.
   23:  */
   24: 
   25: #include <bmon/bmon.h>
   26: #include <bmon/graph.h>
   27: #include <bmon/conf.h>
   28: #include <bmon/output.h>
   29: #include <bmon/node.h>
   30: #include <bmon/utils.h>
   31: 
   32: typedef enum diagram_type_e {
   33: 	D_LIST,
   34: 	D_GRAPH,
   35: 	D_DETAILS
   36: } diagram_type_t;
   37: 
   38: static int c_print_header = INT_MAX;
   39: static diagram_type_t c_diagram_type = D_LIST;
   40: static int c_graph_height = 6;
   41: static int c_quit_after = -1;
   42: 
   43: static inline int get_print_header(void)
   44: {
   45: 	static int hdr_rem;
   46: 
   47: 	if (c_print_header) {
   48: 		if (0 == hdr_rem) {
   49: 			hdr_rem = (c_print_header - 1);
   50: 			return 1;
   51: 		}
   52: 
   53: 		if (c_print_header != INT_MAX)
   54: 			hdr_rem--;
   55: 	}
   56: 
   57: 	return 0;
   58: }
   59: 
   60: static inline void set_diagram_type(const char *t)
   61: {
   62: 	if (tolower(*t) == 'l')
   63: 		c_diagram_type = D_LIST;
   64: 	else if (tolower(*t) == 'g')
   65: 		c_diagram_type = D_GRAPH;
   66: 	else if (tolower(*t) == 'd')
   67: 		c_diagram_type = D_DETAILS;
   68: 	else
   69: 		quit("Unknown diagram type '%s'\n", t);
   70: }
   71: 
   72: 
   73: static void print_item(item_t *i)
   74: {
   75: 	stat_attr_t *bytes, *packets;
   76: 	double rx, tx, rxp, txp;
   77: 	int rxprec, txprec, rxpprec, txpprec;
   78: 	char *rx_u, *tx_u, *rxp_u, *txp_u;
   79: 	char pad[IFNAMSIZ + 32];
   80: 	
   81: 	if (get_print_header()) {
   82: 		printf("Name                      RX Rate         #   %%" \
   83: 		       "     TX Rate         #   %%\n");
   84: 	}
   85: 
   86: 	bytes = lookup_attr(i, i->i_major_attr);
   87: 	packets = lookup_attr(i, i->i_minor_attr);
   88: 
   89: 	rx = cancel_down(attr_get_rx_rate(bytes), bytes->a_unit, &rx_u, &rxprec);
   90: 	tx = cancel_down(attr_get_tx_rate(bytes), bytes->a_unit, &tx_u, &txprec);
   91: 
   92: 	rxp = cancel_down(attr_get_rx_rate(packets), packets->a_unit, &rxp_u, &rxpprec);
   93: 	txp = cancel_down(attr_get_tx_rate(packets), packets->a_unit, &txp_u, &txpprec);
   94: 
   95: 	memset(pad, 0, sizeof(pad));
   96: 	memset(pad, ' ', i->i_level < 15 ? i->i_level : 15);
   97: 
   98: 	strncat(pad, i->i_name, sizeof(pad) - strlen(pad) - 1);
   99: 
  100: 	if (i->i_desc) {
  101: 		strncat(pad, " (", sizeof(pad) - strlen(pad) - 1);
  102: 		strncat(pad, i->i_desc, sizeof(pad) - strlen(pad) - 1);
  103: 		strncat(pad, ")", sizeof(pad) - strlen(pad) - 1);
  104: 	}
  105: 
  106: 	printf("%-22s %8.*f%s %8.*f%s ", pad, rxprec, rx, rx_u, rxpprec, rxp, rxp_u);
  107: 	if (i->i_rx_usage < 0)
  108: 		printf("   ");
  109: 	else
  110: 		printf("%2d%%", i->i_rx_usage);
  111: 
  112: 	printf(" %8.*f%s %8.*f%s ", txprec, tx, tx_u, txpprec, txp, txp_u);
  113: 	if (i->i_tx_usage < 0)
  114: 		printf("   ");
  115: 	else
  116: 		printf("%2d%%", i->i_tx_usage);
  117: 
  118: 	printf("\n");
  119: }
  120: 
  121: 
  122: static void handle_child(item_t *i, void *arg)
  123: {
  124: 	node_t *node = arg;
  125: 
  126: 	print_item(i);
  127: 	foreach_child(node, i, handle_child, node);
  128: }
  129: 
  130: static void print_list(item_t *i, node_t *node)
  131: {
  132: 	if (i->i_flags & ITEM_FLAG_IS_CHILD)
  133: 		return;
  134: 	
  135: 	print_item(i);
  136: 	foreach_child(node, i, handle_child, node);
  137: }
  138: 
  139: static void print_attr_detail(stat_attr_t *a, void *arg)
  140: {
  141: 	char *rx_u, *tx_u;
  142: 	int rxprec, txprec;
  143: 	double rx = cancel_down(attr_get_rx(a), a->a_unit, &rx_u, &rxprec);
  144: 	double tx = cancel_down(attr_get_tx(a), a->a_unit, &tx_u, &txprec);
  145: 
  146: 	printf("  %-14s %12.*f %s %12.*f %s\n",
  147: 	    type2name(a->a_type), rxprec, rx, rx_u, txprec, tx, tx_u);
  148: }
  149: 
  150: static void print_details(item_t *i)
  151: {
  152: 	if (i->i_handle)
  153: 		printf(" %s (%u)\n", i->i_name, i->i_handle);
  154: 	else
  155: 		printf(" %s\n", i->i_name);
  156: 
  157: 	foreach_attr(i, print_attr_detail, NULL);
  158: }
  159: 
  160: static void __print_graph(stat_attr_t *a, void *arg)
  161: {
  162: 	item_t *i = (item_t *) arg;
  163: 	stat_attr_hist_t *h;
  164: 	graph_t *g;
  165: 	int w;
  166: 
  167: 	if (!(a->a_flags & ATTR_FLAG_HISTORY))
  168: 		return;
  169: 
  170: 	h = (stat_attr_hist_t *) a;
  171: 
  172: 	g = create_configued_graph(&h->a_hist, c_graph_height,
  173: 				    h->a_unit, get_x_unit());
  174: 
  175: 	printf("Item: %s\nAttribute: %s\n", i->i_name, type2desc(a->a_type));
  176: 
  177: 	printf("RX   %s\n", g->g_rx.t_y_unit);
  178: 	
  179: 	for (w = (c_graph_height - 1); w >= 0; w--)
  180: 		printf("%8.2f %s\n", g->g_rx.t_y_scale[w],
  181: 		    (char *) g->g_rx.t_data + (w * (HISTORY_SIZE + 1)));
  182: 	
  183: 	printf("         1   5   10   15   20   25   30   35   40   " \
  184: 		"45   50   55   60 %s\n", g->g_rx.t_x_unit);
  185: 
  186: 	printf("TX   %s\n", g->g_tx.t_y_unit);
  187: 	
  188: 	for (w = (c_graph_height - 1); w >= 0; w--)
  189: 		printf("%8.2f %s\n", g->g_tx.t_y_scale[w],
  190: 		    (char *) g->g_tx.t_data + (w * (HISTORY_SIZE + 1)));
  191: 	
  192: 	printf("         1   5   10   15   20   25   30   35   40   " \
  193: 		"45   50   55   60 %s\n", g->g_tx.t_x_unit);
  194: 
  195: 	free_graph(g);
  196: }
  197: 
  198: static void print_graph(item_t *i)
  199: {
  200: 	foreach_attr(i, &__print_graph, i);
  201: }
  202: 
  203: static void ascii_draw_item(item_t *i, void *arg)
  204: {
  205: 	node_t *node = arg;
  206: 
  207: 	switch (c_diagram_type) {
  208: 		case D_LIST:
  209: 			print_list(i, node);
  210: 			break;
  211: 
  212: 		case D_DETAILS:
  213: 			print_details(i);
  214: 			break;
  215: 
  216: 		case D_GRAPH:
  217: 			print_graph(i);
  218: 			break;
  219: 	}
  220: }
  221: 
  222: static void ascii_draw_node(node_t *n, void *arg)
  223: {
  224: 	if (n->n_name) {
  225: 		if (get_nnodes() > 1)
  226: 			printf("%s:\n", n->n_name);
  227: 		foreach_item(n, ascii_draw_item, n);
  228: 	}
  229: }
  230: 
  231: static void ascii_draw(void)
  232: {
  233: 	foreach_node(ascii_draw_node, NULL);
  234: 
  235: 	if (c_quit_after > 0)
  236: 		if (--c_quit_after == 0)
  237: 			exit(0);
  238: }
  239: 
  240: static int ascii_probe(void)
  241: {
  242: 	return 1;
  243: }
  244: 
  245: static void print_help(void)
  246: {
  247: 	printf(
  248: 	"ascii - ASCII Output\n" \
  249: 	"\n" \
  250: 	"  Plain configurable ASCII output.\n" \
  251: 	"\n" \
  252: 	"  vmstat like: (print header every 10 lines)\n" \
  253: 	"      bmon -p eth0 -o ascii:header=10\n" \
  254: 	"  scriptable: (output graph for eth1 10 times)\n" \
  255: 	"      bmon -p eth1 -o 'ascii:diagram=graph;quitafter=10'\n" \
  256: 	"  show details for all ethernet interfaces:\n" \
  257: 	"      bmon -p 'eth*' -o 'ascii:diagram=details;quitafter=1'\n" \
  258: 	"\n" \
  259: 	"  Author: Thomas Graf <tgraf@suug.ch>\n" \
  260: 	"\n" \
  261: 	"  Options:\n" \
  262: 	"    diagram=TYPE   Diagram type\n" \
  263: 	"    fgchar=CHAR    Foreground character (default: '*')\n" \
  264: 	"    bgchar=CHAR    Background character (default: '.')\n" \
  265: 	"    nchar=CHAR     Noise character (default: ':')\n" \
  266: 	"    uchar=CHAR     Unknown character (default: '?')\n" \
  267: 	"    height=NUM     Height of graph (default: 6)\n" \
  268: 	"    xunit=UNIT     X-Axis Unit (default: seconds)\n" \
  269: 	"    yunit=UNIT     Y-Axis Unit (default: dynamic)\n" \
  270: 	"    header[=NUM]   Print header every NUM lines\n" \
  271: 	"    noheader       Do not print a header\n" \
  272: 	"    quitafter=NUM  Quit bmon after NUM outputs\n");
  273: }
  274: 
  275: static void ascii_set_opts(tv_t *attrs)
  276: {
  277: 	while (attrs) {
  278: 		if (!strcasecmp(attrs->type, "diagram") && attrs->value)
  279: 			set_diagram_type(attrs->value);
  280: 		else if (!strcasecmp(attrs->type, "fgchar") && attrs->value)
  281: 			set_fg_char(attrs->value[0]);
  282: 		else if (!strcasecmp(attrs->type, "bgchar") && attrs->value)
  283: 			set_bg_char(attrs->value[0]);
  284: 		else if (!strcasecmp(attrs->type, "nchar") && attrs->value)
  285: 			set_noise_char(attrs->value[0]);
  286: 		else if (!strcasecmp(attrs->type, "uchar") && attrs->value)
  287: 			set_unk_char(attrs->value[0]);
  288: 		else if (!strcasecmp(attrs->type, "xunit") && attrs->value)
  289: 			set_x_unit(attrs->value, 1);
  290: 		else if (!strcasecmp(attrs->type, "yunit") && attrs->value)
  291: 			set_y_unit(attrs->value);
  292: 		else if (!strcasecmp(attrs->type, "height") && attrs->value)
  293: 			c_graph_height = strtol(attrs->value, NULL, 0);
  294: 		else if (!strcasecmp(attrs->type, "header")) {
  295: 			if (attrs->value)
  296: 				c_print_header = strtol(attrs->value, NULL, 0);
  297: 			else
  298: 				c_print_header = INT_MAX;
  299: 		} else if (!strcasecmp(attrs->type, "noheader"))
  300: 			c_print_header = 0;
  301: 		else if (!strcasecmp(attrs->type, "quitafter") && attrs->value)
  302: 			c_quit_after = strtol(attrs->value, NULL, 0);
  303: 		else if (!strcasecmp(attrs->type, "help")) {
  304: 			print_help();
  305: 			exit(0);
  306: 		}
  307: 		
  308: 		attrs = attrs->next;
  309: 	}
  310: }
  311: 
  312: static struct output_module ascii_ops = {
  313: 	.om_name = "ascii",
  314: 	.om_draw = ascii_draw,
  315: 	.om_probe = ascii_probe,
  316: 	.om_set_opts = ascii_set_opts,
  317: };
  318: 
  319: static void __init ascii_init(void)
  320: {
  321: 	register_output_module(&ascii_ops);
  322: }

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