Annotation of embedaddon/bmon/src/out_ascii.c, revision 1.1
1.1 ! misho 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>