ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/statgrab/statgrab.c
(Generate patch)

Comparing projects/libstatgrab/src/statgrab/statgrab.c (file contents):
Revision 1.5 by ats, Thu Aug 28 21:21:32 2003 UTC vs.
Revision 1.17 by tdb, Mon Jan 19 16:49:23 2004 UTC

# Line 1 | Line 1
1   /*
2   * i-scream central monitoring system
3   * http://www.i-scream.org
4 < * Copyright (C) 2000-2003 i-scream
4 > * Copyright (C) 2000-2004 i-scream
5   *
6   * This program is free software; you can redistribute it and/or
7   * modify it under the terms of the GNU General Public License
# Line 16 | Line 16
16   * You should have received a copy of the GNU General Public License
17   * along with this program; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 + *
20 + * $Id$
21   */
22  
23   #ifdef HAVE_CONFIG_H
# Line 66 | Line 68 | display_mode_type display_mode = DISPLAY_LINUX;
68   repeat_mode_type repeat_mode = REPEAT_NONE;
69   int repeat_time = 1;
70   int use_cpu_percent = 0;
71 + int use_diffs = 0;
72  
73   /* Exit with an error message. */
74   void die(const char *s) {
# Line 139 | Line 142 | void add_stat(stat_type type, void *stat, ...) {
142          ++num_stats;
143   }
144  
145 < /* Compare two stats by name, for sorting purposes. */
145 > /* Compare two stats by name for qsort and bsearch. */
146   int stats_compare(const void *a, const void *b) {
147          return strcmp(((stat *)a)->name, ((stat *)b)->name);
148   }
149  
150 < /* Clear and rebuild the stats array. */
151 < void get_stats(int use_diffs) {
152 <        cpu_states_t *cpu_s;
153 <        cpu_percent_t *cpu_p;
151 <        mem_stat_t *mem;
152 <        load_stat_t *load;
153 <        user_stat_t *user;
154 <        swap_stat_t *swap;
155 <        general_stat_t *gen;
156 <        disk_stat_t *disk;
157 <        diskio_stat_t *diskio;
158 <        process_stat_t *proc;
159 <        network_stat_t *net;
160 <        page_stat_t *page;
161 <        static int zero = 0;
162 <        int n, i;
150 > /* Compare up to the length of the key for bsearch. */
151 > int stats_compare_prefix(const void *key, const void *item) {
152 >        const char *kn = ((stat *)key)->name;
153 >        const char *in = ((stat *)item)->name;
154  
155 <        clear_stats();
155 >        return strncmp(kn, in, strlen(kn));
156 > }
157  
158 + void populate_const() {
159 +        static int zero = 0;
160 +
161          /* Constants, for use with MRTG mode. */
162          add_stat(INT, &zero, "const", "0", NULL);
163 + }
164  
165 <        /* FIXME when only fetching some stats, it'd be more efficient to only
170 <           do the libstatgrab calls needed, rather than fetching everything. */
171 <
165 > void populate_cpu() {
166          if (use_cpu_percent) {
167 <                cpu_p = cpu_percent_usage();
167 >                cpu_percent_t *cpu_p = cpu_percent_usage();
168 >
169                  if (cpu_p != NULL) {
170                          add_stat(FLOAT, &cpu_p->user,
171                                   "cpu", "user", NULL);
# Line 184 | Line 179 | void get_stats(int use_diffs) {
179                                   "cpu", "swap", NULL);
180                          add_stat(FLOAT, &cpu_p->nice,
181                                   "cpu", "nice", NULL);
182 <                        add_stat(TIME_T, &cpu_s->systime,
182 >                        add_stat(TIME_T, &cpu_p->time_taken,
183                                   "cpu", "time_taken", NULL);
184                  }
185          } else {
186 +                cpu_states_t *cpu_s;
187 +
188                  cpu_s = use_diffs ? get_cpu_diff() : get_cpu_totals();
189                  if (cpu_s != NULL) {
190                          add_stat(LONG_LONG, &cpu_s->user,
# Line 208 | Line 205 | void get_stats(int use_diffs) {
205                                   "cpu", "systime", NULL);
206                  }
207          }
208 + }
209  
210 <        mem = get_memory_stats();
210 > void populate_mem() {
211 >        mem_stat_t *mem = get_memory_stats();
212 >
213          if (mem != NULL) {
214                  add_stat(LONG_LONG, &mem->total, "mem", "total", NULL);
215                  add_stat(LONG_LONG, &mem->free, "mem", "free", NULL);
216                  add_stat(LONG_LONG, &mem->used, "mem", "used", NULL);
217                  add_stat(LONG_LONG, &mem->cache, "mem", "cache", NULL);
218          }
219 + }
220  
221 <        load = get_load_stats();
221 > void populate_load() {
222 >        load_stat_t *load = get_load_stats();
223 >
224          if (load != NULL) {
225                  add_stat(DOUBLE, &load->min1, "load", "min1", NULL);
226                  add_stat(DOUBLE, &load->min5, "load", "min5", NULL);
227                  add_stat(DOUBLE, &load->min15, "load", "min15", NULL);
228          }
229 + }
230  
231 <        user = get_user_stats();
231 > void populate_user() {
232 >        user_stat_t *user = get_user_stats();
233 >
234          if (user != NULL) {
235                  add_stat(INT, &user->num_entries, "user", "num", NULL);
236                  add_stat(STRING, &user->name_list, "user", "names", NULL);
237          }
238 + }
239  
240 <        swap = get_swap_stats();
240 > void populate_swap() {
241 >        swap_stat_t *swap = get_swap_stats();
242 >
243          if (swap != NULL) {
244                  add_stat(LONG_LONG, &swap->total, "swap", "total", NULL);
245                  add_stat(LONG_LONG, &swap->used, "swap", "used", NULL);
246                  add_stat(LONG_LONG, &swap->free, "swap", "free", NULL);
247          }
248 + }
249  
250 <        gen = get_general_stats();
250 > void populate_general() {
251 >        general_stat_t *gen = get_general_stats();
252 >
253          if (gen != NULL) {
254                  add_stat(STRING, &gen->os_name,
255                           "general", "os_name", NULL);
# Line 249 | Line 261 | void get_stats(int use_diffs) {
261                  add_stat(STRING, &gen->hostname, "general", "hostname", NULL);
262                  add_stat(TIME_T, &gen->uptime, "general", "uptime", NULL);
263          }
264 + }
265  
266 <        disk = get_disk_stats(&n);
266 > void populate_fs() {
267 >        int n, i;
268 >        disk_stat_t *disk = get_disk_stats(&n);
269 >
270          if (disk != NULL) {
271                  for (i = 0; i < n; i++) {
272                          /* FIXME it'd be nicer if libstatgrab did this */
273 <                        const char *name = disk[i].device_name,
274 <                                   *p = strrchr(name, '/');
275 <                        if (p != NULL)
276 <                                name = p + 1;
277 <                        if (*name == '\0')
278 <                                name = "root";
279 <        
273 >                        char *buf, *name, *p;
274 >                        const char *device = disk[i].device_name;
275 >
276 >                        if (strcmp(device, "/") == 0)
277 >                                device = "root";
278 >
279 >                        buf = strdup(device);
280 >                        if (buf == NULL)
281 >                                die("out of memory");
282 >
283 >                        name = buf;
284 >                        if (strlen(name) == 2 && name[1] == ':')
285 >                                name[1] = '\0';
286 >                        if (strncmp(name, "/dev/", 5) == 0)
287 >                                name += 5;
288 >                        while ((p = strchr(name, '/')) != NULL)
289 >                                *p = '_';
290 >
291                          add_stat(STRING, &disk[i].device_name,
292                                   "fs", name, "device_name", NULL);
293                          add_stat(STRING, &disk[i].fs_type,
# Line 279 | Line 306 | void get_stats(int use_diffs) {
306                                   "fs", name, "used_inodes", NULL);
307                          add_stat(LONG_LONG, &disk[i].free_inodes,
308                                   "fs", name, "free_inodes", NULL);
309 +
310 +                        free(buf);
311                  }
312          }
313 + }
314  
315 + void populate_disk() {
316 +        int n, i;
317 +        diskio_stat_t *diskio;
318 +
319          diskio = use_diffs ? get_diskio_stats_diff(&n) : get_diskio_stats(&n);
320          if (diskio != NULL) {
321                  for (i = 0; i < n; i++) {
# Line 297 | Line 331 | void get_stats(int use_diffs) {
331                                   "disk", name, "systime", NULL);
332                  }
333          }
334 + }
335  
336 <        proc = get_process_stats();
336 > void populate_proc() {
337 >        process_stat_t *proc = get_process_stats();
338 >
339          if (proc != NULL) {
340                  add_stat(INT, &proc->total, "proc", "total", NULL);
341                  add_stat(INT, &proc->running, "proc", "running", NULL);
# Line 306 | Line 343 | void get_stats(int use_diffs) {
343                  add_stat(INT, &proc->stopped, "proc", "stopped", NULL);
344                  add_stat(INT, &proc->zombie, "proc", "zombie", NULL);
345          }
346 + }
347  
348 + void populate_net() {
349 +        int n, i;
350 +        network_stat_t *net;
351 +
352          net = use_diffs ? get_network_stats_diff(&n) : get_network_stats(&n);
353          if (net != NULL) {
354                  for (i = 0; i < n; i++) {
# Line 322 | Line 364 | void get_stats(int use_diffs) {
364                                   "net", name, "systime", NULL);
365                  }
366          }
367 + }
368  
369 + void populate_page() {
370 +        page_stat_t *page;
371 +
372          page = use_diffs ? get_page_stats_diff() : get_page_stats();
373          if (page != NULL) {
374                  add_stat(LONG_LONG, &page->pages_pagein, "page", "in", NULL);
375                  add_stat(LONG_LONG, &page->pages_pageout, "page", "out", NULL);
376 <                add_stat(LONG_LONG, &page->systime, "page", "systime", NULL);
376 >                add_stat(TIME_T, &page->systime, "page", "systime", NULL);
377          }
378 + }
379  
380 + typedef struct {
381 +        const char *name;
382 +        void (*populate)();
383 +        int interesting;
384 + } toplevel;
385 + toplevel toplevels[] = {
386 +        {"const.", populate_const, 0},
387 +        {"cpu.", populate_cpu, 0},
388 +        {"mem.", populate_mem, 0},
389 +        {"load.", populate_load, 0},
390 +        {"user.", populate_user, 0},
391 +        {"swap.", populate_swap, 0},
392 +        {"general.", populate_general, 0},
393 +        {"fs.", populate_fs, 0},
394 +        {"disk.", populate_disk, 0},
395 +        {"proc.", populate_proc, 0},
396 +        {"net.", populate_net, 0},
397 +        {"page.", populate_page, 0},
398 +        {NULL, NULL, 0}
399 + };
400 +
401 + /* Set the "interesting" flag on the sections that we actually need to
402 +   fetch. */
403 + void select_interesting(int argc, char **argv) {
404 +        toplevel *t;
405 +
406 +        if (argc == 0) {
407 +                for (t = &toplevels[0]; t->name != NULL; t++)
408 +                        t->interesting = 1;
409 +        } else {
410 +                int i;
411 +
412 +                for (i = 0; i < argc; i++) {
413 +                        for (t = &toplevels[0]; t->name != NULL; t++) {
414 +                                if (strncmp(argv[i], t->name,
415 +                                            strlen(t->name)) == 0) {
416 +                                        t->interesting = 1;
417 +                                        break;
418 +                                }
419 +                        }
420 +                }
421 +        }
422 + }
423 +
424 + /* Clear and rebuild the stats array. */
425 + void get_stats() {
426 +        toplevel *t;
427 +
428 +        clear_stats();
429 +
430 +        for (t = &toplevels[0]; t->name != NULL; t++) {
431 +                if (t->interesting)
432 +                        t->populate();
433 +        }
434 +
435          qsort(stats, num_stats, sizeof *stats, stats_compare);
436   }
437  
# Line 389 | Line 491 | void print_stats(int argc, char **argv) {
491          } else {
492                  /* Print selected stats. */
493                  for (i = optind; i < argc; i++) {
494 +                        char *name = argv[i];
495                          stat key;
496 <                        const stat *s;
496 >                        const stat *s, *end;
497 >                        int (*compare)(const void *, const void *);
498  
499 <                        key.name = argv[i];
499 >                        key.name = name;
500 >                        if (name[strlen(name) - 1] == '.')
501 >                                compare = stats_compare_prefix;
502 >                        else
503 >                                compare = stats_compare;
504 >
505                          s = (const stat *)bsearch(&key, stats, num_stats,
506 <                                                  sizeof *stats,
507 <                                                  stats_compare);
508 <                        if (s != NULL) {
506 >                                                  sizeof *stats, compare);
507 >                        if (s == NULL) {
508 >                                printf("Unknown stat %s\n", name);
509 >                                continue;
510 >                        }
511 >
512 >                        /* Find the range of stats the user wanted. */
513 >                        for (; s >= stats; s--) {
514 >                                if (compare(&key, s) != 0)
515 >                                        break;
516 >                        }
517 >                        s++;
518 >                        for (end = s; end < &stats[num_stats]; end++) {
519 >                                if (compare(&key, end) != 0)
520 >                                        break;
521 >                        }
522 >
523 >                        /* And print them. */
524 >                        for (; s < end; s++) {
525                                  print_stat(s);
526                          }
527                  }
# Line 405 | Line 530 | void print_stats(int argc, char **argv) {
530  
531   void usage() {
532          printf("Usage: statgrab [OPTION]... [STAT]...\n"
533 <               "Display system statistics (all statistics by default).\n"
533 >               "Display system statistics.\n"
534 >               "\n"
535 >               "If no STATs are given, all will be displayed. Specify 'STAT.' to display all\n"
536 >               "statistics starting with that prefix.\n"
537                 "\n");
538          printf("  -l         Linux sysctl-style output (default)\n"
539                 "  -b         BSD sysctl-style output\n"
# Line 472 | Line 600 | int main(int argc, char **argv) {
600          if (use_cpu_percent && repeat_mode == REPEAT_NONE)
601                  die("CPU percentage usage display requires stat differences");
602  
603 +        if (repeat_mode == REPEAT_NONE)
604 +                use_diffs = 0;
605 +        else
606 +                use_diffs = 1;
607 +
608 +        select_interesting(argc - optind, &argv[optind]);
609 +
610 +        /* We don't care if statgrab_init fails, because we can just display
611 +           the statistics that can be read as non-root. */
612 +        statgrab_init();
613 +        if (statgrab_drop_privileges() != 0)
614 +                die("Failed to drop setuid/setgid privileges");
615 +
616          switch (repeat_mode) {
617          case REPEAT_NONE:
618 <                get_stats(0);
618 >                get_stats();
619                  print_stats(argc, argv);
620                  break;
621          case REPEAT_ONCE:
622 <                get_stats(1);
622 >                get_stats();
623                  sleep(repeat_time);
624 <                get_stats(1);
624 >                get_stats();
625                  print_stats(argc, argv);
626                  break;
627          case REPEAT_FOREVER:
628                  while (1) {
629 <                        get_stats(1);
629 >                        get_stats();
630                          print_stats(argc, argv);
631                          printf("\n");
632                          sleep(repeat_time);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines