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>