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

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.2 ! misho     104:        double rx = unit_value2str(a->a_rx_rate.r_total,
        !           105:                                   a->a_def->ad_unit,
        !           106:                                   &rx_u, &rxprec);
        !           107:        double tx = unit_value2str(a->a_tx_rate.r_total,
        !           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       misho     215: 
                    216:        if (c_quit_after > 0)
                    217:                if (--c_quit_after == 0)
                    218:                        exit(0);
                    219: }
                    220: 
                    221: static void print_help(void)
                    222: {
                    223:        printf(
                    224:        "ascii - ASCII Output\n" \
                    225:        "\n" \
                    226:        "  Plain configurable ASCII output.\n" \
                    227:        "\n" \
                    228:        "  scriptable: (output graph for eth1 10 times)\n" \
                    229:        "      bmon -p eth1 -o 'ascii:diagram=graph;quitafter=10'\n" \
                    230:        "  show details for all ethernet interfaces:\n" \
                    231:        "      bmon -p 'eth*' -o 'ascii:diagram=details;quitafter=1'\n" \
                    232:        "\n" \
                    233:        "  Author: Thomas Graf <tgraf@suug.ch>\n" \
                    234:        "\n" \
                    235:        "  Options:\n" \
                    236:        "    diagram=TYPE   Diagram type\n" \
                    237:        "    fgchar=CHAR    Foreground character (default: '*')\n" \
                    238:        "    bgchar=CHAR    Background character (default: '.')\n" \
                    239:        "    nchar=CHAR     Noise character (default: ':')\n" \
                    240:        "    uchar=CHAR     Unknown character (default: '?')\n" \
                    241:        "    height=NUM     Height of graph (default: 6)\n" \
                    242:        "    xunit=UNIT     X-Axis Unit (default: seconds)\n" \
                    243:        "    yunit=UNIT     Y-Axis Unit (default: dynamic)\n" \
                    244:        "    quitafter=NUM  Quit bmon after NUM outputs\n");
                    245: }
                    246: 
1.1.1.2 ! misho     247: static void ascii_parse_opt(const char *type, const char *value)
1.1       misho     248: {
1.1.1.2 ! misho     249:        if (!strcasecmp(type, "diagram") && value) {
        !           250:                if (tolower(*value) == 'l')
        !           251:                        c_diagram_type = D_LIST;
        !           252:                else if (tolower(*value) == 'g')
        !           253:                        c_diagram_type = D_GRAPH;
        !           254:                else if (tolower(*value) == 'd')
        !           255:                        c_diagram_type = D_DETAILS;
        !           256:                else
        !           257:                        quit("Unknown diagram type '%s'\n", value);
        !           258:        } else if (!strcasecmp(type, "fgchar") && value)
        !           259:                graph_cfg.gc_foreground = value[0];
        !           260:        else if (!strcasecmp(type, "bgchar") && value)
        !           261:                graph_cfg.gc_background = value[0];
        !           262:        else if (!strcasecmp(type, "nchar") && value)
        !           263:                graph_cfg.gc_noise = value[0];
        !           264: #if 0
        !           265:        else if (!strcasecmp(type, "uchar") && value)
        !           266:                set_unk_char(value[0]);
        !           267: #endif
        !           268:        else if (!strcasecmp(type, "xunit") && value)
        !           269:                c_hist = strdup(value);
        !           270: #if 0
        !           271:        else if (!strcasecmp(type, "yunit") && value) {
        !           272:                struct unit *u;
        !           273: 
        !           274:                if (!(u = unit_lookup(value)))
        !           275:                        quit("Unknown unit '%s'\n", value);
        !           276: 
        !           277:                graph_cfg.gc_unit = u;
        !           278: #endif
        !           279:        else if (!strcasecmp(type, "height") && value)
        !           280:                graph_cfg.gc_height = strtol(value, NULL, 0);
        !           281:        else if (!strcasecmp(type, "quitafter") && value)
        !           282:                c_quit_after = strtol(value, NULL, 0);
        !           283:        else if (!strcasecmp(type, "help")) {
        !           284:                print_help();
        !           285:                exit(0);
        !           286:        } else
        !           287:                quit("Unknown module option '%s'\n", type);
        !           288: }
        !           289: 
        !           290: static struct bmon_module ascii_ops = {
        !           291:        .m_name         = "ascii",
        !           292:        .m_do           = ascii_draw,
        !           293:        .m_parse_opt    = ascii_parse_opt,
1.1       misho     294: };
                    295: 
                    296: static void __init ascii_init(void)
                    297: {
1.1.1.2 ! misho     298:        output_register(&ascii_ops);
1.1       misho     299: }

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