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>