@cryptotaxi247 / netdata-1 / commits / f97b71f1e

fixed white space on mobile devices, added cpu graphs

Costa Tsaousis (ktsaou) committed Apr 2, 2014 at 01:21 UTC f97b71f1e44d0195c980fc564d4b3b11a3e98147
4 files changed +337 -58
netdata.c
+281 -33
@@ -33,6 +33,7 @@
33
34 #define RRD_DIMENSION_ABSOLUTE 0
35 #define RRD_DIMENSION_INCREMENTAL 1
36 +#define RRD_DIMENSION_PCENT_OVER_TOTAL 2
37
38 #define RRD_TYPE_NET "net"
39 #define RRD_TYPE_NET_LEN strlen(RRD_TYPE_NET)
@@ -52,6 +53,9 @@
53 #define RRD_TYPE_NET_IPVS "ipvs"
54 #define RRD_TYPE_NET_IPVS_LEN strlen(RRD_TYPE_NET_IPVS)
55
56 +#define RRD_TYPE_STAT "cpu"
57 +#define RRD_TYPE_STAT_LEN strlen(RRD_TYPE_STAT)
58 +
59 #define WEB_PATH_FILE "file"
60 #define WEB_PATH_DATA "data"
61 #define WEB_PATH_GRAPH "graph"
@@ -120,6 +124,9 @@
124 #define MAX_PROC_NET_IPVS_LINE 4096
125 #define MAX_PROC_NET_IPVS_NAME 1024
126
127 +#define MAX_PROC_STAT_LINE 4096
128 +#define MAX_PROC_STAT_NAME 1024
129 +
130
131 int silent = 0;
132 int save_history = HISTORY;
@@ -131,7 +138,7 @@ int listen_port = LISTEN_PORT;
138 // helpers
139
140 unsigned long long usecdiff(struct timeval *now, struct timeval *last) {
134 - return ((((now->tv_sec * 1000000) + now->tv_usec) - ((last->tv_sec * 1000000) + last->tv_usec)));
141 + return ((((now->tv_sec * 1000000L) + now->tv_usec) - ((last->tv_sec * 1000000L) + last->tv_usec)));
142 }
143
144 // ----------------------------------------------------------------------------
@@ -338,6 +345,7 @@ struct rrd_dimension {
345 size_t entries;
346
347 int type;
348 + int hidden; // if set to non zero, this dimension will not be sent to the client
349
350 long multiplier;
351 long divisor;
@@ -592,6 +600,19 @@ void rrd_stats_done(RRD_STATS *st)
600 pthread_mutex_unlock(&st->mutex);
601 }
602
603 +int rrd_stats_dimension_hide(RRD_STATS *st, const char *id)
604 +{
605 + RRD_DIMENSION *rd = rrd_stats_dimension_find(st, id);
606 + if(!rd) {
607 + error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
608 + return 1;
609 + }
610 +
611 + rd->hidden = 1;
612 + return 0;
613 +}
614 +
615 +
616 int rrd_stats_dimension_set(RRD_STATS *st, const char *id, void *data)
617 {
618 RRD_DIMENSION *rd = rrd_stats_dimension_find(st, id);
@@ -640,7 +661,7 @@ size_t rrd_stats_one_json(RRD_STATS *st, char *options, char *buffer, size_t len
661 i += sprintf(&buffer[i], "\t\t\t\"name\" : \"%s\",\n", st->name);
662 i += sprintf(&buffer[i], "\t\t\t\"type\" : \"%s\",\n", st->type);
663 i += sprintf(&buffer[i], "\t\t\t\"title\" : \"%s %s\",\n", st->title, st->name);
643 - i += sprintf(&buffer[i], "\t\t\t\"usertitle\" : \"%s %s (%s)\",\n", st->title, st->usertitle, st->name);
664 + i += sprintf(&buffer[i], "\t\t\t\"usertitle\" : \"%s %s (%s)\",\n", st->title, st->usertitle, st->id);
665 i += sprintf(&buffer[i], "\t\t\t\"userpriority\" : \"%s\",\n", st->userpriority);
666 i += sprintf(&buffer[i], "\t\t\t\"envtitle\" : \"%s\",\n", st->envtitle);
667 i += sprintf(&buffer[i], "\t\t\t\"envpriority\" : \"%s\",\n", st->envpriority);
@@ -685,6 +706,29 @@ size_t rrd_stats_all_json(char *buffer, size_t len)
706 return(i);
707 }
708
709 +long long rrd_stats_dimension_get(RRD_DIMENSION *rd, size_t position)
710 +{
711 + if(rd->bytes == sizeof(long long)) {
712 + long long *dimension = rd->values;
713 + return(dimension[position]);
714 + }
715 + else if(rd->bytes == sizeof(long)) {
716 + long *dimension = rd->values;
717 + return(dimension[position]);
718 + }
719 + else if(rd->bytes == sizeof(int)) {
720 + int *dimension = rd->values;
721 + return(dimension[position]);
722 + }
723 + else if(rd->bytes == sizeof(char)) {
724 + char *dimension = rd->values;
725 + return(dimension[position]);
726 + }
727 + else fatal("Cannot produce JSON for size %d bytes dimension.", rd->bytes);
728 +
729 + return(0);
730 +}
731 +
732 size_t rrd_stats_json(RRD_STATS *st, char *b, size_t length, size_t entries_to_show, size_t group_count, int group_method)
733 {
734 pthread_mutex_lock(&st->mutex);
@@ -709,9 +753,13 @@ size_t rrd_stats_json(RRD_STATS *st, char *b, size_t length, size_t entries_to_s
753 unsigned long long usec = 0;// usec between the entries
754 char dtm[201]; // temp variable for storing dates
755
756 + int we_need_totals = 0; // if set, we should calculate totals for all dimensions
757 +
758 // find how many dimensions we have
713 - for( rd = st->dimensions ; rd ; rd = rd->next)
759 + for( rd = st->dimensions ; rd ; rd = rd->next) {
760 dimensions++;
761 + if(rd->type == RRD_DIMENSION_PCENT_OVER_TOTAL) we_need_totals++;
762 + }
763
764 if(!dimensions) {
765 pthread_mutex_unlock(&st->mutex);
@@ -725,10 +773,11 @@ size_t rrd_stats_json(RRD_STATS *st, char *b, size_t length, size_t entries_to_s
773 group_values[c] = group_counts[c] = 0;
774
775 i += sprintf(&b[i], "{\n \"cols\":\n [\n");
728 - i += sprintf(&b[i], " {\"id\":\"\",\"label\":\"time\",\"pattern\":\"\",\"type\":\"datetime\"},\n");
776 + i += sprintf(&b[i], " {\"id\":\"\",\"label\":\"time\",\"pattern\":\"\",\"type\":\"datetime\"}");
777
778 for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++)
731 - i += sprintf(&b[i], " {\"id\":\"\",\"label\":\"%s\",\"pattern\":\"\",\"type\":\"number\"}%s\n", rd->name, rd->next?",":"");
779 + if(!rd->hidden)
780 + i += sprintf(&b[i], ",\n {\"id\":\"\",\"label\":\"%s\",\"pattern\":\"\",\"type\":\"number\"}", rd->name);
781
782 i += sprintf(&b[i], " ],\n \"rows\":\n [\n");
783
@@ -777,37 +826,31 @@ size_t rrd_stats_json(RRD_STATS *st, char *b, size_t length, size_t entries_to_s
826 sprintf(dtm, "\"Date(%d, %d, %d, %d, %d, %d, %d)\"", tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(st->times[t].tv_usec / 1000)); // datetime
827 // strftime(dtm, 200, "\"Date(%Y, %m, %d, %H, %M, %S)\"", tm); // datetime
828 // strftime(dtm, 200, "[%H, %M, %S, 0]", tm); // timeofday
780 - i += sprintf(&b[i], "%s {\"c\":[{\"v\":%s},", printed?"]},\n":"", dtm);
829 + i += sprintf(&b[i], "%s {\"c\":[{\"v\":%s}", printed?"]},\n":"", dtm);
830
831 printed++;
832 }
833
834 + // if we need a PCENT_OVER_TOTAL, calculate the totals for the current and the last
835 + long long total = 0, oldtotal = 0;
836 + if(we_need_totals) {
837 + for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
838 + total += rrd_stats_dimension_get(rd, t);
839 + oldtotal += rrd_stats_dimension_get(rd, lt);
840 + }
841 + }
842 +
843 for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
786 - long long oldvalue = 0, value = 0; // temp variable for storing data values
844 + long long oldvalue, value; // temp variable for storing data values
845
788 - if(rd->bytes == sizeof(long long)) {
789 - long long *dimension = rd->values;
790 - value = dimension[t];
791 - oldvalue = dimension[lt];
792 - }
793 - else if(rd->bytes == sizeof(long)) {
794 - long *dimension = rd->values;
795 - value = dimension[t];
796 - oldvalue = dimension[lt];
797 - }
798 - else if(rd->bytes == sizeof(int)) {
799 - int *dimension = rd->values;
800 - value = dimension[t];
801 - oldvalue = dimension[lt];
802 - }
803 - else if(rd->bytes == sizeof(char)) {
804 - char *dimension = rd->values;
805 - value = dimension[t];
806 - oldvalue = dimension[lt];
807 - }
808 - else fatal("Cannot produce JSON for size %d bytes dimension.", rd->bytes);
846 + value = rrd_stats_dimension_get(rd, t);
847 + oldvalue = rrd_stats_dimension_get(rd, lt);
848
849 switch(rd->type) {
850 + case RRD_DIMENSION_PCENT_OVER_TOTAL:
851 + value = 100 * (value - oldvalue) / (total - oldtotal);
852 + break;
853 +
854 case RRD_DIMENSION_INCREMENTAL:
855 if(oldvalue > value) value = 0; // detect overflows and resets
856 else value -= oldvalue;
@@ -834,7 +877,9 @@ size_t rrd_stats_json(RRD_STATS *st, char *b, size_t length, size_t entries_to_s
877 }
878
879 if(((count-pad) % group_count) == 0) {
837 - i += sprintf(&b[i], "{\"v\":%lld}%s", group_values[c], rd->next?",":"");
880 + if(!rd->hidden)
881 + i += sprintf(&b[i], ",{\"v\":%lld}", group_values[c]);
882 +
883 group_values[c] = group_counts[c] = 0;
884 }
885 }
@@ -1169,6 +1214,7 @@ void web_client_process(struct web_client *w)
1214
1215 // do we have such a data set?
1216 RRD_STATS *st = rrd_stats_find_byname(tok);
1217 + if(!st) st = rrd_stats_find(tok);
1218 if(!st) {
1219 // we don't have it
1220 // try to send a file with that name
@@ -2000,11 +2046,11 @@ int do_proc_net_snmp() {
2046 if(r == EOF) break;
2047 if(r != 19) error("Cannot read /proc/net/snmp IP line. Expected 19 params, read %d.", r);
2048
2003 - RRD_STATS *st = rrd_stats_find(RRD_TYPE_NET_SNMP ".ip");
2049 + RRD_STATS *st = rrd_stats_find(RRD_TYPE_NET_SNMP ".packets");
2050 if(!st) {
2005 - st = rrd_stats_create(RRD_TYPE_NET_SNMP ".ip", RRD_TYPE_NET_SNMP ".ip", save_history, "IPv4 Packets", "Packets/s", RRD_TYPE_NET_SNMP);
2051 + st = rrd_stats_create(RRD_TYPE_NET_SNMP ".packets", RRD_TYPE_NET_SNMP ".packets", save_history, "IPv4 Packets", "Packets/s", RRD_TYPE_NET_SNMP);
2052 if(!st) {
2007 - error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET_SNMP ".ip");
2053 + error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET_SNMP ".packets");
2054 continue;
2055 }
2056
@@ -2399,6 +2445,205 @@ int do_proc_net_ip_vs_stats() {
2445 return 0;
2446 }
2447
2448 +int do_proc_stat() {
2449 + char buffer[MAX_PROC_STAT_LINE+1] = "";
2450 +
2451 + FILE *fp = fopen("/proc/stat", "r");
2452 + if(!fp) {
2453 + error("Cannot read /proc/stat.");
2454 + return 1;
2455 + }
2456 +
2457 + for(;1;) {
2458 + char *p = fgets(buffer, MAX_PROC_STAT_LINE, fp);
2459 + if(!p) break;
2460 +
2461 + if(strncmp(p, "cpu", 3) == 0) {
2462 + char id[MAX_PROC_STAT_NAME + 1] = RRD_TYPE_STAT ".";
2463 + unsigned long long user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice;
2464 + char *name = &id[RRD_TYPE_STAT_LEN + 1];
2465 +
2466 + int r = sscanf(buffer, "%s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
2467 + name, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, &guest_nice);
2468 +
2469 + if(r == EOF) break;
2470 + if(r != 11) error("Cannot read /proc/stat cpu line. Expected 11 params, read %d.", r);
2471 +
2472 + RRD_STATS *st = rrd_stats_find(id);
2473 + if(!st) {
2474 + st = rrd_stats_create(id, id, save_history, "Time for ", "Percentage", RRD_TYPE_STAT);
2475 + if(!st) {
2476 + error("Cannot create RRD_STATS for %s.", id);
2477 + continue;
2478 + }
2479 +
2480 + if(strcmp(id, "cpu.cpu") == 0) strcpy(st->usertitle, "all CPUs");
2481 + else strcpy(st->usertitle, name);
2482 +
2483 + long multiplier = 1;
2484 + long divisor = 1; // sysconf(_SC_CLK_TCK);
2485 +
2486 + if(!rrd_stats_dimension_add(st, "iowait", "iowait", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2487 + error("Cannot add RRD_STATS dimension %s.", "iowait");
2488 +
2489 + if(!rrd_stats_dimension_add(st, "nice", "nice", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2490 + error("Cannot add RRD_STATS dimension %s.", "nice");
2491 +
2492 + if(!rrd_stats_dimension_add(st, "system", "system", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2493 + error("Cannot add RRD_STATS dimension %s.", "system");
2494 +
2495 + if(!rrd_stats_dimension_add(st, "user", "user", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2496 + error("Cannot add RRD_STATS dimension %s.", "user");
2497 +
2498 + if(!rrd_stats_dimension_add(st, "idle", "idle", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2499 + error("Cannot add RRD_STATS dimension %s.", "idle");
2500 + else rrd_stats_dimension_hide(st, "idle");
2501 +
2502 + if(!rrd_stats_dimension_add(st, "irq", "irq", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2503 + error("Cannot add RRD_STATS dimension %s.", "irq");
2504 +
2505 + if(!rrd_stats_dimension_add(st, "softirq", "softirq", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2506 + error("Cannot add RRD_STATS dimension %s.", "softirq");
2507 +
2508 + if(!rrd_stats_dimension_add(st, "steal", "steal", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2509 + error("Cannot add RRD_STATS dimension %s.", "steal");
2510 +
2511 + if(!rrd_stats_dimension_add(st, "guest", "guest", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2512 + error("Cannot add RRD_STATS dimension %s.", "guest");
2513 +
2514 + if(!rrd_stats_dimension_add(st, "guest_nice", "guest_nice", sizeof(unsigned long long), multiplier, divisor, RRD_DIMENSION_PCENT_OVER_TOTAL))
2515 + error("Cannot add RRD_STATS dimension %s.", "guest_nice");
2516 +
2517 + }
2518 + else rrd_stats_next(st);
2519 +
2520 + rrd_stats_dimension_set(st, "user", &user);
2521 + rrd_stats_dimension_set(st, "nice", &nice);
2522 + rrd_stats_dimension_set(st, "system", &system);
2523 + rrd_stats_dimension_set(st, "idle", &idle);
2524 + rrd_stats_dimension_set(st, "iowait", &iowait);
2525 + rrd_stats_dimension_set(st, "irq", &irq);
2526 + rrd_stats_dimension_set(st, "softirq", &softirq);
2527 + rrd_stats_dimension_set(st, "steal", &steal);
2528 + rrd_stats_dimension_set(st, "guest", &guest);
2529 + rrd_stats_dimension_set(st, "guest_nice", &guest_nice);
2530 + rrd_stats_done(st);
2531 + }
2532 + else if(strncmp(p, "intr ", 5) == 0) {
2533 + char id[MAX_PROC_STAT_NAME + 1] = RRD_TYPE_STAT ".";
2534 + char *name = &id[RRD_TYPE_STAT_LEN + 1];
2535 +
2536 + unsigned long long value;
2537 +
2538 + int r = sscanf(buffer, "%s %llu ", name, &value);
2539 + if(r == EOF) break;
2540 + if(r != 2) error("Cannot read /proc/stat intr line. Expected 2 params, read %d.", r);
2541 +
2542 + RRD_STATS *st = rrd_stats_find(id);
2543 + if(!st) {
2544 + st = rrd_stats_create(id, id, save_history, "CPU Interrupts", "interrupts/s", RRD_TYPE_STAT);
2545 + if(!st) {
2546 + error("Cannot create RRD_STATS for %s.", id);
2547 + continue;
2548 + }
2549 +
2550 + if(!rrd_stats_dimension_add(st, "interrupts", "interrupts", sizeof(unsigned long long), 1, 1, RRD_DIMENSION_INCREMENTAL))
2551 + error("Cannot add RRD_STATS dimension %s.", "interrupts");
2552 +
2553 + }
2554 + else rrd_stats_next(st);
2555 +
2556 + rrd_stats_dimension_set(st, "interrupts", &value);
2557 + rrd_stats_done(st);
2558 + }
2559 + else if(strncmp(p, "ctxt ", 5) == 0) {
2560 + char id[MAX_PROC_STAT_NAME + 1] = RRD_TYPE_STAT ".";
2561 + char *name = &id[RRD_TYPE_STAT_LEN + 1];
2562 +
2563 + unsigned long long value;
2564 +
2565 + int r = sscanf(buffer, "%s %llu ", name, &value);
2566 + if(r == EOF) break;
2567 + if(r != 2) error("Cannot read /proc/stat ctxt line. Expected 2 params, read %d.", r);
2568 +
2569 + RRD_STATS *st = rrd_stats_find(id);
2570 + if(!st) {
2571 + st = rrd_stats_create(id, id, save_history, "CPU Context Switches", "context switches/s", RRD_TYPE_STAT);
2572 + if(!st) {
2573 + error("Cannot create RRD_STATS for %s.", id);
2574 + continue;
2575 + }
2576 +
2577 + if(!rrd_stats_dimension_add(st, "switches", "switches", sizeof(unsigned long long), 1, 1, RRD_DIMENSION_INCREMENTAL))
2578 + error("Cannot add RRD_STATS dimension %s.", "switches");
2579 +
2580 + }
2581 + else rrd_stats_next(st);
2582 +
2583 + rrd_stats_dimension_set(st, "switches", &value);
2584 + rrd_stats_done(st);
2585 + }
2586 + else if(strncmp(p, "processes ", 10) == 0) {
2587 + char id[MAX_PROC_STAT_NAME + 1] = RRD_TYPE_STAT ".";
2588 + char *name = &id[RRD_TYPE_STAT_LEN + 1];
2589 +
2590 + unsigned long long value;
2591 +
2592 + int r = sscanf(buffer, "%s %llu ", name, &value);
2593 + if(r == EOF) break;
2594 + if(r != 2) error("Cannot read /proc/stat processes line. Expected 2 params, read %d.", r);
2595 +
2596 + RRD_STATS *st = rrd_stats_find(id);
2597 + if(!st) {
2598 + st = rrd_stats_create(id, id, save_history, "Started Processes", "processes started", RRD_TYPE_STAT);
2599 + if(!st) {
2600 + error("Cannot create RRD_STATS for %s.", id);
2601 + continue;
2602 + }
2603 +
2604 + if(!rrd_stats_dimension_add(st, "started", "started", sizeof(unsigned long long), 1, 1, RRD_DIMENSION_INCREMENTAL))
2605 + error("Cannot add RRD_STATS dimension %s.", "started");
2606 +
2607 + }
2608 + else rrd_stats_next(st);
2609 +
2610 + rrd_stats_dimension_set(st, "started", &value);
2611 + rrd_stats_done(st);
2612 + }
2613 + else if(strncmp(p, "procs_running ", 14) == 0) {
2614 + char id[MAX_PROC_STAT_NAME + 1] = RRD_TYPE_STAT ".";
2615 + char *name = &id[RRD_TYPE_STAT_LEN + 1];
2616 +
2617 + unsigned long long value;
2618 +
2619 + int r = sscanf(buffer, "%s %llu ", name, &value);
2620 + if(r == EOF) break;
2621 + if(r != 2) error("Cannot read /proc/stat processes line. Expected 2 params, read %d.", r);
2622 +
2623 + RRD_STATS *st = rrd_stats_find(id);
2624 + if(!st) {
2625 + st = rrd_stats_create(id, id, save_history, "CPU Running Processes", "processes running", RRD_TYPE_STAT);
2626 + if(!st) {
2627 + error("Cannot create RRD_STATS for %s.", id);
2628 + continue;
2629 + }
2630 +
2631 + if(!rrd_stats_dimension_add(st, "running", "running", sizeof(unsigned long long), 1, 1, RRD_DIMENSION_ABSOLUTE))
2632 + error("Cannot add RRD_STATS dimension %s.", "running");
2633 +
2634 + }
2635 + else rrd_stats_next(st);
2636 +
2637 + rrd_stats_dimension_set(st, "running", &value);
2638 + rrd_stats_done(st);
2639 + }
2640 + }
2641 +
2642 + fclose(fp);
2643 + return 0;
2644 +}
2645 +
2646 +
2647 // ----------------------------------------------------------------------------
2648 // /proc processor
2649
@@ -2416,6 +2661,7 @@ void *proc_main(void *ptr)
2661 int vdo_proc_net_netstat = 0;
2662 int vdo_proc_net_stat_conntrack = 0;
2663 int vdo_proc_net_ip_vs_stats = 0;
2664 + int vdo_proc_stat = 0;
2665
2666 for(;1;) {
2667 unsigned long long usec, susec;
@@ -2432,6 +2678,7 @@ void *proc_main(void *ptr)
2678 if(!vdo_proc_net_netstat) vdo_proc_net_netstat = do_proc_net_netstat(usec);
2679 if(!vdo_proc_net_stat_conntrack) vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(usec);
2680 if(!vdo_proc_net_ip_vs_stats) vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(usec);
2681 + if(!vdo_proc_stat) vdo_proc_stat = do_proc_stat(usec);
2682 // END -- the job is done
2683
2684 // find the time to sleep in order to wait exactly update_every seconds
@@ -2716,6 +2963,7 @@ void sig_handler(int signo)
2963 case SIGQUIT:
2964 case SIGINT:
2965 case SIGHUP:
2966 + case SIGSEGV:
2967 error("Signaled cleanup (signal %d).", signo);
2968 if(tc_child_pid) kill(tc_child_pid, SIGTERM);
2969 tc_child_pid = 0;
@@ -2874,7 +3122,7 @@ int main(int argc, char **argv)
3122 atexit(bye);
3123
3124 // catch all signals
2877 - for (i = 1 ; i < 65 ;i++) signal(i, sig_handler);
3125 + for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i, sig_handler);
3126
3127
3128 pthread_t p_proc, p_tc;
web/index.html
+29 -22
@@ -5,6 +5,8 @@
5 <meta charset="utf-8">
6 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7 <meta name="viewport" content="width=device-width, initial-scale=1">
8 + <meta name="apple-mobile-web-app-capable" content="yes">
9 + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
10 <meta name="description" content="">
11 <meta name="author" content="costa@tsaousis.gr">
12
@@ -35,7 +37,7 @@
37 var mycharts = new Array();
38 var mainchart;
39
38 - function chartIsLoadingHTML(width, height) { return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading chart<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
40 + function chartIsLoadingHTML(width, height) { return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\" style=\"vertical-align:middle\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading chart<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
41
42 function showChartIsLoading(id, width, height) { document.getElementById(id).innerHTML = chartIsLoadingHTML(width, height); }
43
@@ -53,19 +55,11 @@
55
56 mainchart.thumbnail = false;
57 mainchart.group = 5;
56 - mainchart.group_method = "max";
58 mainchart.div = 'maingraph';
59 mainchart.last_updated = 0;
60 mainchart.explorer = false;
61
61 - if(mainchart.type == "tc") {
62 - mainchart.group = 15;
63 - mainchart.group_method = "average";
64 - }
65 - else if(mainchart.type == "ipv4" || mainchart.type == "conntrack" || mainchart.type == "ipvs") {
66 - mainchart.group = 15;
67 - mainchart.group_method = "max";
68 - }
62 + if(mainchart.chartOptions.isStacked) mainchart.group = 15;
63
64 // calculate the time to refresh each chart
65 mainchart.chart_update_every = mainchart.group * 1000; // milliseconds
@@ -150,6 +144,8 @@
144 var width = thumbWidth();
145 var height = 200;
146
147 + document.getElementById('splash').height = $(window).height() * 0.95;
148 +
149 loadCharts(function(c) {
150 mycharts = c;
151
@@ -158,7 +154,7 @@
154 return;
155 }
156
161 - var thumbsContainer = document.getElementById("graphs");
157 + var thumbsContainer = document.getElementById("thumbgraphs");
158 if(!thumbsContainer) {
159 alert("Cannot find the thumbsContainer");
160 return;
@@ -184,43 +180,41 @@
180 case "tc":
181 c.glyphicon = "glyphicon-transfer";
182 c.group = 30;
187 - c.group_method = "average";
183 break;
184
185 case "net":
186 c.glyphicon = "glyphicon-cloud";
187 c.group = 10;
193 - c.group_method = "max";
188 break;
189
190 case "ipv4":
191 c.glyphicon = "glyphicon-resize-full";
192 c.group = 30;
199 - c.group_method = "max";
193 break;
194
195 case "conntrack":
196 c.glyphicon = "glyphicon-eye-open";
197 c.group = 30;
205 - c.group_method = "max";
198 break;
199
200 case "ipvs":
201 c.glyphicon = "glyphicon-sort";
202 c.group = 30;
211 - c.group_method = "max";
203 break;
204
205 case "disk":
206 c.glyphicon = "glyphicon-floppy-disk";
207 c.group = 20;
217 - c.group_method = "max";
208 + break;
209 +
210 + case "cpu":
211 + c.glyphicon = "glyphicon-search";
212 + c.group = 10;
213 break;
214
215 default:
216 c.glyphicon = "glyphicon-search";
217 c.group = 60;
223 - c.group_method = "max";
218 break;
219 }
220
@@ -259,8 +253,9 @@
253 else if(a.name == "conntrack") a.priority = 3;
254 else if(a.name == "ipvs") a.priority = 4;
255 else if(a.name == "ipv4") a.priority = 5;
262 - else if(a.name == "disk") a.priority = 6;
263 - else a.priority = 4;
256 + else if(a.name == "cpu") a.priority = 6;
257 + else if(a.name == "disk") a.priority = 7;
258 + else a.priority = 99;
259
260 a.html = "<tr><td><ol class=\"breadcrumb graphs\"><li class=\"active\"><span class=\"glyphicon " + a.glyphicon + "\"></span> &nbsp; <a id=\"" + a.name + "\" href=\"#" + a.name + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";
261 });
@@ -401,8 +396,20 @@
396 </div>
397
398 <div class="container graphs" id="thumbgraphs_container">
404 - <div class="allgraphs" id="graphs">
405 - <table width="100%"><tr><td align="center"><p/>&nbsp;<p/>&nbsp;<p/>&nbsp;<h1><span class="glyphicon glyphicon-refresh"></span><br/><br/>loading charts<br/><br/><span class="label label-default">Please wait...</span></h1></td></tr></table>
399 + <div class="allgraphs" id="thumbgraphs">
400 + <table width="100%" height="95%">
401 + <tr><td id="splash" align="center" style="vertical-align:middle">
402 + <h1>
403 + Welcome to <b>NetData</b>!
404 + <br/><br/>
405 + <span class="glyphicon glyphicon-refresh"></span>
406 + <br/><br/>
407 + loading charts
408 + <br/><br/>
409 + <span class="label label-default">Please wait...</span>
410 + </h1>
411 + </td></tr>
412 + </table>
413 </div>
414 </div>
415 </html>
web/netdata.js
+18 -3
@@ -8,7 +8,10 @@ function refreshChart(chart, doNext) {
8 chart.refreshCount++;
9
10 if(chart.chart != null) {
11 - if(chart.chart.getSelection()[0]) return;
11 + if(chart.chart.getSelection()[0]) {
12 + if(typeof doNext == "function") doNext();
13 + return;
14 + }
15 }
16
17 var url = chart.url;
@@ -97,7 +100,15 @@ function loadCharts(doNext) {
100 };
101
102 // set the chart type
100 - if((json.charts[i].type == "ipv4" || json.charts[i].type == "ipv6" || json.charts[i].type == "ipvs" || json.charts[i].type == "conntrack")
103 + if((json.charts[i].type == "ipv4"
104 + || json.charts[i].type == "ipv6"
105 + || json.charts[i].type == "ipvs"
106 + || json.charts[i].type == "conntrack"
107 + || json.charts[i].id == "cpu.ctxt"
108 + || json.charts[i].id == "cpu.intr"
109 + || json.charts[i].id == "cpu.processes"
110 + || json.charts[i].id == "cpu.procs_running"
111 + )
112 && json.charts[i].name != "ipv4.net" && json.charts[i].name != "ipvs.net") {
113
114 // default for all LineChart
@@ -105,7 +116,7 @@ function loadCharts(doNext) {
116 json.charts[i].chartOptions.lineWidth = 3;
117 json.charts[i].chartOptions.curveType = 'function';
118 }
108 - else if(json.charts[i].type == "tc") {
119 + else if(json.charts[i].type == "tc" || json.charts[i].type == "cpu") {
120
121 // default for all stacked AreaChart
122 json.charts[i].chartType = "AreaChart";
@@ -125,6 +136,10 @@ function loadCharts(doNext) {
136
137 // the category name, and other options, per type
138 switch(json.charts[i].type) {
139 + case "cpu":
140 + json.charts[i].category = "CPU";
141 + break;
142 +
143 case "tc":
144 json.charts[i].category = "Quality of Service";
145 break;
web/theme.css
+9
@@ -1,4 +1,13 @@
1 +/* http://stackoverflow.com/questions/17005500/bootstrap-css-responsive-left-with-a-white-space-on-the-right */
2 +
3 +html {
4 + width: auto !important;
5 + overflow-x: hidden !important;
6 +}
7 +
8 body {
9 + width: auto !important;
10 + overflow-x: hidden !important;
11 padding-top: 70px;
12 padding-bottom: 30px;
13 }