Annotation of embedaddon/bmon/src/out_ascii.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  * out_ascii.c           ASCII Output
                      3:  *
1.1.1.2   misho       4:  * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
                      5:  * Copyright (c) 2013 Red Hat, Inc.
1.1       misho       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>
1.1.1.2   misho      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>
1.1       misho      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: 
1.1.1.2   misho      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: 
1.1       misho      50: static diagram_type_t c_diagram_type = D_LIST;
1.1.1.2   misho      51: static char *c_hist = "second";
1.1       misho      52: static int c_quit_after = -1;
                     53: 
1.1.1.2   misho      54: static void print_list(struct element *e)
1.1       misho      55: {
1.1.1.2   misho      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;
1.1       misho      59:        char pad[IFNAMSIZ + 32];
1.1.1.2   misho      60:        struct attr *a;
1.1       misho      61: 
1.1.1.2   misho      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);
1.1       misho      71: 
                     72:        memset(pad, 0, sizeof(pad));
1.1.1.2   misho      73:        memset(pad, ' ', e->e_level < 15 ? e->e_level : 15);
1.1       misho      74: 
1.1.1.2   misho      75:        strncat(pad, e->e_name, sizeof(pad) - strlen(pad) - 1);
1.1       misho      76: 
1.1.1.2   misho      77:        if (e->e_description) {
1.1       misho      78:                strncat(pad, " (", sizeof(pad) - strlen(pad) - 1);
1.1.1.2   misho      79:                strncat(pad, e->e_description, sizeof(pad) - strlen(pad) - 1);
1.1       misho      80:                strncat(pad, ")", sizeof(pad) - strlen(pad) - 1);
                     81:        }
                     82: 
1.1.1.2   misho      83:        printf("  %-36s %8.*f%-3s %8.*f%-3s ",
                     84:               pad, rx1prec, rx1, rxu1, rx2prec, rx2, rxu2);
1.1       misho      85: 
1.1.1.2   misho      86:        if (e->e_rx_usage == FLT_MAX)
1.1       misho      87:                printf("   ");
                     88:        else
1.1.1.2   misho      89:                printf("%2.0f%%", e->e_rx_usage);
1.1       misho      90: 
1.1.1.2   misho      91:        printf("  %8.*f%-3s %8.*f%-3s ", tx1prec, tx1, txu1, tx2prec, tx2, txu2);
1.1       misho      92: 
1.1.1.2   misho      93:        if (e->e_tx_usage == FLT_MAX)
                     94:                printf("   \n");
                     95:        else
                     96:                printf("%2.0f%%\n", e->e_tx_usage);
                     97: }
1.1       misho      98: 
1.1.1.2   misho      99: static void print_attr_detail(struct element *e, struct attr *a, void *arg)
1.1       misho     100: {
1.1.1.2   misho     101:        char *rx_u, *tx_u;
                    102:        int rxprec, txprec;
1.1       misho     103: 
1.1.1.3 ! misho     104:        double rx = unit_value2str(rate_get_total(&a->a_rx_rate),
1.1.1.2   misho     105:                                   a->a_def->ad_unit,
                    106:                                   &rx_u, &rxprec);
1.1.1.3 ! misho     107:        double tx = unit_value2str(rate_get_total(&a->a_tx_rate),
1.1.1.2   misho     108:                                   a->a_def->ad_unit,
                    109:                                   &tx_u, &txprec);
1.1       misho     110: 
1.1.1.2   misho     111:        printf("  %-36s %12.*f%-3s %12.*f%-3s\n",
                    112:               a->a_def->ad_description, rxprec, rx, rx_u, txprec, tx, tx_u);
1.1       misho     113: }
                    114: 
1.1.1.2   misho     115: static void print_details(struct element *e)
1.1       misho     116: {
1.1.1.2   misho     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);
1.1       misho     125: 
1.1.1.2   misho     126:        printf("\n");
1.1       misho     127: }
                    128: 
1.1.1.2   misho     129: static void print_table(struct graph *g, struct graph_table *tbl, const char *hdr)
1.1       misho     130: {
1.1.1.2   misho     131:        int i;
1.1       misho     132: 
1.1.1.2   misho     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");
1.1       misho     144: }
                    145: 
1.1.1.2   misho     146: static void __print_graph(struct element *e, struct attr *a, void *arg)
1.1       misho     147: {
1.1.1.2   misho     148:        struct history *h;
                    149:        struct graph *g;
1.1       misho     150: 
1.1.1.2   misho     151:        if (!(a->a_flags & ATTR_DOING_HISTORY))
1.1       misho     152:                return;
                    153: 
1.1.1.2   misho     154:        graph_cfg.gc_unit = a->a_def->ad_unit;
1.1       misho     155: 
1.1.1.2   misho     156:        list_for_each_entry(h, &a->a_history_list, h_list) {
                    157:                if (strcasecmp(c_hist, h->h_definition->hd_name))
                    158:                        continue;
1.1       misho     159: 
1.1.1.2   misho     160:                g = graph_alloc(h, &graph_cfg);
                    161:                graph_refill(g, h);
1.1       misho     162: 
1.1.1.2   misho     163:                printf("Interface: %s\n", e->e_name);
                    164:                printf("Attribute: %s\n", a->a_def->ad_description);
1.1       misho     165: 
1.1.1.2   misho     166:                print_table(g, &g->g_rx, "RX");
                    167:                print_table(g, &g->g_tx, "TX");
                    168: 
                    169:                graph_free(g);
1.1       misho     170: 
1.1.1.2   misho     171:        }
1.1       misho     172: }
                    173: 
1.1.1.2   misho     174: static void print_graph(struct element *e)
1.1       misho     175: {
1.1.1.2   misho     176:        element_foreach_attr(e, __print_graph, NULL);
1.1       misho     177: }
                    178: 
1.1.1.2   misho     179: static void ascii_draw_element(struct element_group *g, struct element *e,
                    180:                               void *arg)
1.1       misho     181: {
                    182:        switch (c_diagram_type) {
                    183:                case D_LIST:
1.1.1.2   misho     184:                        print_list(e);
1.1       misho     185:                        break;
                    186: 
                    187:                case D_DETAILS:
1.1.1.2   misho     188:                        print_details(e);
1.1       misho     189:                        break;
                    190: 
                    191:                case D_GRAPH:
1.1.1.2   misho     192:                        print_graph(e);
1.1       misho     193:                        break;
                    194:        }
                    195: }
                    196: 
1.1.1.2   misho     197: static void ascii_draw_group(struct element_group *g, void *arg)
1.1       misho     198: {
1.1.1.2   misho     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);
1.1       misho     210: }
                    211: 
                    212: static void ascii_draw(void)
                    213: {
1.1.1.2   misho     214:        group_foreach(ascii_draw_group, NULL);
1.1.1.3 ! misho     215:        fflush(stdout);
1.1       misho     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: 
1.1.1.2   misho     248: static void ascii_parse_opt(const char *type, const char *value)
1.1       misho     249: {
1.1.1.2   misho     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,
1.1       misho     295: };
                    296: 
                    297: static void __init ascii_init(void)
                    298: {
1.1.1.2   misho     299:        output_register(&ascii_ops);
1.1       misho     300: }

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