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