Diff for /embedaddon/bmon/src/out_format.c between versions 1.1 and 1.1.1.3

version 1.1, 2012/02/21 22:19:56 version 1.1.1.3, 2019/10/21 14:58:35
Line 1 Line 1
 /*  /*
  * out_format.c         Formatted Output   * out_format.c         Formatted Output
  *   *
 * Copyright (c) 2001-2004 Thomas Graf <tgraf@suug.ch> * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
  * Copyright (c) 2013 Red Hat, Inc.
  *   *
  * Permission is hereby granted, free of charge, to any person obtaining a   * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),   * copy of this software and associated documentation files (the "Software"),
Line 26 Line 27
 #include <bmon/graph.h>  #include <bmon/graph.h>
 #include <bmon/conf.h>  #include <bmon/conf.h>
 #include <bmon/output.h>  #include <bmon/output.h>
   #include <bmon/group.h>
   #include <bmon/element.h>
 #include <bmon/input.h>  #include <bmon/input.h>
 #include <bmon/node.h>  
 #include <bmon/utils.h>  #include <bmon/utils.h>
   #include <bmon/attr.h>
   
 static int c_quit_after = -1;  static int c_quit_after = -1;
 static char *c_format;  static char *c_format;
Line 48  static struct out_token { Line 51  static struct out_token {
 static int token_index;  static int token_index;
 static int out_tokens_size;  static int out_tokens_size;
   
static inline char *itos(b_cnt_t n)static char *get_token(struct element_group *g, struct element *e,
                        const char *token, char *buf, size_t len)
 {  {
        static char str[128];        if (!strncasecmp(token, "group:", 6)) {
        snprintf(str, sizeof(str), "%" PRIu64, n);                const char *n = token + 6;
        return str; 
} 
   
static char *get_token(node_t *node, item_t *it, const char *token)                if (!strcasecmp(n, "nelements")) {
{                        snprintf(buf, len, "%u", g->g_nelements);
        if (!strcasecmp(token, "node:index"))                        return buf;
                return itos(node->n_index);                } else if (!strcasecmp(n, "name"))
        else if (!strcasecmp(token, "node:name"))                        return g->g_name;
                return node->n_name;                else if (!strcasecmp(n, "title"))
        else if (!strcasecmp(token, "node:from"))                        return g->g_hdr->gh_title;
                return node->n_from;
        else if (!strcasecmp(token, "node:nitems"))        } else if (!strncasecmp(token, "element:", 8)) {
                return itos(node->n_nitems);                const char *n = token + 8;
        else if (!strcasecmp(token, "node:rx_maj_total"))
                return itos(node->n_rx_maj_total);                if (!strcasecmp(n, "name"))
        else if (!strcasecmp(token, "node:tx_maj_total"))                        return e->e_name;
                return itos(node->n_tx_maj_total);                else if (!strcasecmp(n, "description"))
        else if (!strcasecmp(token, "node:rx_min_total"))                        return e->e_description;
                return itos(node->n_rx_min_total);                else if (!strcasecmp(n, "nattrs")) {
        else if (!strcasecmp(token, "node:tx_min_total"))                        snprintf(buf, len, "%u", e->e_nattrs);
                return itos(node->n_tx_min_total);                        return buf;
        else if (!strcasecmp(token, "item:name"))                } else if (!strcasecmp(n, "lifecycles")) {
                return it->i_name;                        snprintf(buf, len, "%u", e->e_lifecycles);
        else if (!strcasecmp(token, "item:desc"))                        return buf;
                return it->i_desc ? it->i_desc : "none";                } else if (!strcasecmp(n, "level")) {
        else if (!strcasecmp(token, "item:index"))                        snprintf(buf, len, "%u", e->e_level);
                return itos(it->i_index);                        return buf;
        else if (!strcasecmp(token, "item:nattrs"))                } else if (!strcasecmp(n, "parent"))
                return itos(it->i_nattrs);                        return e->e_parent ? e->e_parent->e_name : "";
        else if (!strcasecmp(token, "item:lifetime"))                else if (!strcasecmp(n, "id")) {
                return itos(it->i_lifetime);                        snprintf(buf, len, "%u", e->e_id);
        else if (!strcasecmp(token, "item:level"))                        return buf;
                return itos(it->i_level);                } else if (!strcasecmp(n, "rxusage")) {
        else if (!strcasecmp(token, "item:link"))                        snprintf(buf, len, "%2.0f",
                return itos(it->i_link);                                e->e_rx_usage == FLT_MAX ? e->e_rx_usage : 0.0f);
        else if (!strcasecmp(token, "item:parent"))                        return buf;
                return itos(it->i_parent);                } else if (!strcasecmp(n, "txusage")) {
        else if (!strcasecmp(token, "item:handle"))                        snprintf(buf, len, "%2.0f",
                return itos(it->i_handle);                                e->e_tx_usage == FLT_MAX ? e->e_tx_usage : 0.0f);
        else if (!strcasecmp(token, "item:rxusage"))                        return buf;
                return it->i_rx_usage == -1 ? "UNK" : itos(it->i_rx_usage);                } else if (!strcasecmp(n, "haschilds")) {
        else if (!strcasecmp(token, "item:txusage"))                        snprintf(buf, len, "%u",
                return it->i_tx_usage == -1 ? "UNK" : itos(it->i_tx_usage);                                list_empty(&e->e_childs) ? 0 : 1);
        else if (!strcasecmp(token, "item:is_child"))                        return buf;
                return itos(!!(it->i_flags & ITEM_FLAG_IS_CHILD));                }
        else if (!strcasecmp(token, "item:has_childs"))        } else if (!strncasecmp(token, "attr:", 5)) {
                return itos(!!(it->i_flags & ITEM_FLAG_HAS_CHILDS));                const char *type = token + 5;
        else if (!strcasecmp(token, "read:sec"))                char *name = strchr(type, ':');
                return itos(rtiming.rt_last_read.tv_sec);                struct attr_def *def;
        else if (!strcasecmp(token, "read:usec"))                struct attr *a;
                return itos(rtiming.rt_last_read.tv_usec);
        else if (!strncasecmp(token, "attr:", 5)) {                if (!name) {
                int atype; 
                char *name = strchr(token+5, ':'); 
                stat_attr_t *a; 
                if (name == NULL) { 
                         fprintf(stderr, "Invalid attribute field \"%s\"\n",                          fprintf(stderr, "Invalid attribute field \"%s\"\n",
                            token);                                type);
                        return "UNK";                        goto out;
                 }                  }
                 atype = name2type(++name);  
   
                if (atype == INT_MAX || !(a = lookup_attr(it, atype))) {                name++;
                        fprintf(stderr, "Unknown attribute \"%s\"\n", name);
                        return "UNK";                def = attr_def_lookup(name);
                 if (!def) {
                         fprintf(stderr, "Undefined attribute \"%s\"\n", name);
                         goto out;
                 }                  }
   
                if (!strncasecmp(token+5, "rx:", 3))                if (!(a = attr_lookup(e, def->ad_id)))
                        return itos(attr_get_rx(a));                        goto out;
                else if (!strncasecmp(token+5, "tx:", 3))
                        return itos(attr_get_tx(a));                if (!strncasecmp(type, "rx:", 3)) {
                else if (!strncasecmp(token+5, "rxrate:", 7))                        snprintf(buf, len, "%" PRIu64, rate_get_total(&a->a_rx_rate));
                        return itos(attr_get_rx_rate(a));                        return buf;
                else if (!strncasecmp(token+5, "txrate:", 7))                } else if (!strncasecmp(type, "tx:", 3)) {
                        return itos(attr_get_tx_rate(a));                        snprintf(buf, len, "%" PRIu64, rate_get_total(&a->a_tx_rate));
                else if (!strncasecmp(token+5, "rx64:", 5)) {                        return buf;
                        return a->a_rx.r_is64bit ? "1" : "0";                } else if (!strncasecmp(type, "rxrate:", 7)) {
                } else if (!strncasecmp(token+5, "tx64:", 5)) {                        snprintf(buf, len, "%.2f", a->a_rx_rate.r_rate);
                        return a->a_tx.r_is64bit ? "1" : "0";                        return buf;
                } else if (!strncasecmp(token+5, "rxoflows:", 9)) {                } else if (!strncasecmp(type, "txrate:", 7)) {
                        return itos(a->a_rx.r_overflows);                        snprintf(buf, len, "%.2f", a->a_tx_rate.r_rate);
                } else if (!strncasecmp(token+5, "txoflows:", 9)) {                        return buf;
                        return itos(a->a_tx.r_overflows);                }
                } else if (!strncasecmp(token+5, "rxenab:", 7)) 
                        return itos(!!(a->a_flags & ATTR_FLAG_RX_ENABLED)); 
                else if (!strncasecmp(token+5, "txenab:", 7)) 
                        return itos(!!(a->a_flags & ATTR_FLAG_TX_ENABLED)); 
         }          }
   
         fprintf(stderr, "Unknown field \"%s\"\n", token);          fprintf(stderr, "Unknown field \"%s\"\n", token);
        return "UNK";out:
         return "unknown";
 }  }
   
static void format_draw_item(item_t *it, void *arg)static void draw_element(struct element_group *g, struct element *e, void *arg)
 {  {
         int i;          int i;
         node_t *node = (node_t *) arg;  
   
         for (i = 0; i < token_index; i++) {          for (i = 0; i < token_index; i++) {
                if (out_tokens[i].ot_type == OT_STRING) {                char buf[128];
                        fprintf(c_fd, "%s", out_tokens[i].ot_str);                char *p;
                } else if (out_tokens[i].ot_type == OT_TOKEN)
                        fprintf(c_fd, "%s", get_token(node, it, out_tokens[i].ot_str));                if (out_tokens[i].ot_type == OT_STRING)
                         p = out_tokens[i].ot_str;
                 else if (out_tokens[i].ot_type == OT_TOKEN)
                         p = get_token(g, e, out_tokens[i].ot_str,
                                       buf, sizeof(buf));
                 else
                         BUG();
 
                 if (p)
                         fprintf(c_fd, "%s", p);
         }          }
 }  }
   
 static void format_draw_node(node_t *n, void *arg)  
 {  
         foreach_item(n, format_draw_item, n);  
 }  
   
 static void format_draw(void)  static void format_draw(void)
 {  {
        foreach_node(format_draw_node, NULL);        group_foreach_recursive(draw_element, NULL);
         fflush(stdout);
   
         if (c_quit_after > 0)          if (c_quit_after > 0)
                 if (--c_quit_after == 0)                  if (--c_quit_after == 0)
Line 187  static inline void add_token(int type, char *data) Line 188  static inline void add_token(int type, char *data)
                 if (out_tokens == NULL)                  if (out_tokens == NULL)
                         quit("Cannot reallocate out token array\n");                          quit("Cannot reallocate out token array\n");
         }          }
                
                
         out_tokens[token_index].ot_type = type;          out_tokens[token_index].ot_type = type;
         out_tokens[token_index].ot_str = data;          out_tokens[token_index].ot_str = data;
         token_index++;          token_index++;
Line 248  static int format_probe(void) Line 249  static int format_probe(void)
                         }                          }
   
                         goto out;                          goto out;
                
 finish_escape:  finish_escape:
                         *p = '\0';                          *p = '\0';
                         add_token(OT_STRING, s);                          add_token(OT_STRING, s);
Line 257  finish_escape: Line 258  finish_escape:
                         continue;                          continue;
                 }                  }
   
out:    out:
                 if (new_one) {                  if (new_one) {
                         add_token(OT_STRING, p);                          add_token(OT_STRING, p);
                         new_one = 0;                          new_one = 0;
Line 296  static void print_help(void) Line 297  static void print_help(void)
         "  Options:\n" \          "  Options:\n" \
         "    fmt=FORMAT     Format string\n" \          "    fmt=FORMAT     Format string\n" \
         "    stderr         Write to stderr instead of stdout\n" \          "    stderr         Write to stderr instead of stdout\n" \
        "    quitafter=NUM  Quit bmon NUM outputs\n" \        "    quitafter=NUM  Quit bmon after NUM outputs\n" \
         "\n" \          "\n" \
         "  Placeholders:\n" \          "  Placeholders:\n" \
        "    read:sec              time of last read (seconds)\n" \        "    group:nelements       Number of elements this group\n" \
        "    read:usec             time of last read (micro seconds)\n" \        "         :name            Name of group\n" \
        "    node:index            index of node\n" \        "         :title           Title of group\n" \
        "    node:name             name of node\n" \        "    element:name          Name of element\n" \
        "    node:from             origin this node came from\n" \        "           :desc          Description of element\n" \
        "    node:nitems           number of items this nodes carries\n" \        "           :nattrs        Number of attributes\n" \
        "    node:rx_maj_total     total RX rate of major attribute\n" \        "           :lifecycles    Number of lifecycles\n" \
        "    node:tx_maj_total     total TX rate of major attribute\n" \        "           :level         Indentation level\n" \
        "    node:rx_min_total     total RX rate of minor attribute\n" \        "           :parent        Name of parent element\n" \
        "    node:tx_min_total     total TX rate of minor attribute\n" \        "           :rxusage       RX usage in percent\n" \
        "    item:name             name of item\n" \        "           :txusage       TX usage in percent)\n" \
        "    item:desc             description of item\n" \        "           :id            ID of element\n" \
        "    item:index            index of item\n" \        "           :haschilds     Indicate if element has children (0|1)\n" \
        "    item:nattrs           number of attributes this item carries\n" \        "    attr:rx:<name>        RX counter of attribute <name>\n" \
        "    item:lifetime         lifetime of item\n" \        "        :tx:<name>        TX counter of attribute <name>\n" \
        "    item:level            indentation level of item\n" \        "        :rxrate:<name>    RX rate of attribute <name>\n" \
        "    item:link             item index of root parent\n" \        "        :txrate:<name>    TX rate of attribute <name>\n" \
        "    item:parent           item index of parent\n" \ 
        "    item:rxusage          RX usage of item (in percent)\n" \ 
        "    item:txusage          TX usage of item (in percent)\n" \ 
        "    item:handle           handle of item\n" \ 
        "    item:is_child         1 if item is a child\n" \ 
        "    item:has_childs       1 if item has childs\n" \ 
        "    attr:rx:<name>        rx counter of attribute <name>\n" \ 
        "    attr:tx:<name>        tx counter of attribute <name>\n" \ 
        "    attr:rxrate:<name>    rx rate of attribute <name>\n" \ 
        "    attr:txrate:<name>    tx rate of attribute <name>\n" \ 
        "    attr:rx64:<name>      1 if rx counter of attribute <name> is 64bit sized\n" \ 
        "    attr:tx64:<name>      1 if tx counter of attribute <name> is 64bit sized\n" \ 
        "    attr:rxoflows:<name>  number of rx counter overflows of attribute <name>\n" \ 
        "    attr:txoflows:<name>  number of tx counter overflows of attribute <name>\n" \ 
        "    attr:rxenab:<name>    1 if rx counter of attribute <name> is available\n" \ 
        "    attr:txenab:<name>    1 if rx counter of attribute <name> is available\n" \ 
         "\n" \          "\n" \
         "  Supported Escape Sequences: \\n, \\t, \\r, \\v, \\b, \\f, \\a\n" \          "  Supported Escape Sequences: \\n, \\t, \\r, \\v, \\b, \\f, \\a\n" \
         "\n" \          "\n" \
         "  Examples:\n" \          "  Examples:\n" \
        "    \"$(node:name)\\t$(item:name)\\t$(attr:rx:bytes)\\t$(attr:tx:bytes)\\n\"\n" \        "    '$(element:name)\\t$(attr:rx:bytes)\\t$(attr:tx:bytes)\\n'\n" \
        "    axs     lo      12074   12074\n" \        "    lo      12074   12074\n" \
         "\n" \          "\n" \
        "    \"$(item:name) $(attr:rxrate:packets) $(attr:txrate:packets)\\n\"\n" \        "    '$(element:name) $(attr:rxrate:packets) $(attr:txrate:packets)\\n'\n" \
         "    eth0 33 5\n" \          "    eth0 33 5\n" \
         "\n" \          "\n" \
        "    \"Node: $(node:name)\\nItem: $(item:name)\\nBytes Rate: \" \\\n" \        "    'Item: $(element:name)\\nBytes Rate: $(attr:rxrate:bytes)/" \
        "        \"$(attr:rxrate:bytes)/$(attr:txrate:bytes)\\nPackets Rate: \" \\\n" \        "$(attr:txrate:bytes)\\nPackets Rate: $(attr:rxrate:packets)/" \
        "        \"$(attr:rxrate:packets)/$(attr:txrate:packets)\\n\"\n" \        "$(attr:txrate:packets)\\n'\n" \
        "    Node: axs\n" \ 
         "    Item: eth0\n" \          "    Item: eth0\n" \
         "    Bytes Rate: 49130/2119\n" \          "    Bytes Rate: 49130/2119\n" \
         "    Packets Rate: 40/11\n" \          "    Packets Rate: 40/11\n" \
         "\n");          "\n");
 }  }
   
static void format_set_opts(tv_t *attrs)static void format_parse_opt(const char *type, const char *value)
 {  {
        while (attrs) {        if (!strcasecmp(type, "stderr"))
                if (!strcasecmp(attrs->type, "stderr"))                c_fd = stderr;
                        c_fd = stderr;        else if (!strcasecmp(type, "debug"))
                else if (!strcasecmp(attrs->type, "debug"))                c_debug = 1;
                        c_debug = 1;        else if (!strcasecmp(type, "fmt")) {
                else if (!strcasecmp(attrs->type, "fmt")) {                if (c_format)
                        if (c_format)                        free(c_format);
                                free(c_format);                c_format = strdup(value);
                        c_format = strdup(attrs->value);        } else if (!strcasecmp(type, "quitafter") &&
                } else if (!strcasecmp(attrs->type, "quitafter") &&                               value)
                                       attrs->value)                c_quit_after = strtol(value, NULL, 0);
                        c_quit_after = strtol(attrs->value, NULL, 0);        else if (!strcasecmp(type, "help")) {
                else if (!strcasecmp(attrs->type, "help")) {                print_help();
                        print_help();                exit(0);
                        exit(0); 
                } 
                 
                attrs = attrs->next; 
         }          }
 }  }
   
static struct output_module format_ops = {static struct bmon_module format_ops = {
        .om_name = "format",        .m_name          = "format",
        .om_draw = format_draw,        .m_do                = format_draw,
        .om_probe = format_probe,        .m_probe = format_probe,
        .om_set_opts = format_set_opts,        .m_parse_opt    = format_parse_opt,
 };  };
   
 static void __init ascii_init(void)  static void __init ascii_init(void)
 {  {
         c_fd = stdout;          c_fd = stdout;
        c_format = strdup("$(node:name) $(item:name) $(attr:rx:bytes) $(attr:tx:bytes) " \        c_format = strdup("$(element:name) $(attr:rx:bytes) $(attr:tx:bytes) " \
             "$(attr:rx:packets) $(attr:tx:packets)\\n");              "$(attr:rx:packets) $(attr:tx:packets)\\n");
        register_output_module(&format_ops);
         output_register(&format_ops);
 }  }

Removed from v.1.1  
changed lines
  Added in v.1.1.1.3


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