@cryptotaxi247 / netdata-1 / commits / 840a0ee85

settled all issues; added more options; final tests for merging into production

Costa Tsaousis (ktsaou) committed May 1, 2014 at 02:45 UTC 840a0ee8575c8b97f3f8ee7acdf1f4a0f375ba77
3 files changed +327 -174
charts.d/skeleton-chart.sh
+26 -17
@@ -18,17 +18,19 @@ test $update_every -eq 0 && update_every=1 # if it is zero, make it 1
18 echo "MYPID $$"
19
20 # -----------------------------------------------------------------------------
21 -# create a new chart
22 -# > CHART type.chartname family[=chartname] homegroup[=type] charttype[=line] priority[=1000] update_every[=user default]
23 -# charttype = line, area or stacked
24 -# homegroup = any name or the word 'none' which hides the chart from the home web page
25 -#
26 -# set the chart title
27 -# > TITLE My Super Title
21 +# DOCUMENTATION
22 +#
23 +# This is a long doc, to describe a simple procedure.
24 +# If you don't want to read it, just skip at the end to see the action...
25 #
29 -# set the units of measurement
30 -# > UNITS my wonderfull unit
26 +# CREATE NEW CHART:
27 +# > CHART type.chartname title units family[=chartname] category[=type] charttype[=line] priority[=1000] update_every[=user default]
28 #
29 +# where
30 +# - charttype = line, area or stacked
31 +# - family is used to group charts together (for example all eth0 charts should say: eth0)
32 +# - category = is the home page section: any name or the word 'none' which hides the chart from the home web page
33 +#
34 # create all the dimensions you need
35 # > DIMENSION CREATE dimensionname algorithm multiplier divisor [hidden]"
36 #
@@ -71,20 +73,27 @@ echo "MYPID $$"
73 # So, at the chart level:
74 #
75 # - the finest number is 0.1
74 -# - the smallest -214.748.364,7
76 +# - the smallest -214.748.364,8
77 # - the highest 214.748.364,7
78 #
79 # You should choose a multiplier and divider to stay within these limits.
80 #
81 +# Example:
82 +# eth0 bytes-in is a 64bit number that is incremented every time.
83 +# let say it is 1.000.000.000.000.000.000 and one second later it is 1.000.000.000.999.000.000
84 +# the dimension is 'incremental' with multiplier 8 (bytes to bits) and divider 1024 (bits to kilobits).
85 +# netdata will store this value:
86 +#
87 +# value = (1.000.000.000.000.000.000 - 1.000.000.000.999.000.000) * 10 * 8 / 1024 = 78.046.875
88 +# or 7.804.687,5 kilobits/second (a little less than 8 gigabits/second)
89 +#
90 +
91
92 cat <<EOF
81 -CHART example.random ExampleGroup ExampleCategory stacked 1 1
82 -TITLE Random Numbers Example Chart
83 -UNITS random numbers
84 -UPDATE EVERY $update_every
85 -DIMENSION number1 absolute unsigned int 1 1
86 -DIMENSION number2 absolute unsigned int 1 1
87 -DIMENSION number3 absolute unsigned int 1 1
93 +CHART example.random "Random Numbers Example Chart" "random numbers" ExampleFamily ExampleCategory stacked 500 $update_every
94 +DIMENSION number1 absolute 1 1
95 +DIMENSION number2 absolute 1 1
96 +DIMENSION number3 absolute 1 1 hidden
97 EOF
98
99 # You can create more charts if you like.
netdata.c
+274 -112
@@ -150,7 +150,7 @@ int listen_port = LISTEN_PORT;
150 // helpers
151
152 unsigned long long usecdiff(struct timeval *now, struct timeval *last) {
153 - return ((((now->tv_sec * 1000000L) + now->tv_usec) - ((last->tv_sec * 1000000L) + last->tv_usec)));
153 + return ((((now->tv_sec * 1000000ULL) + now->tv_usec) - ((last->tv_sec * 1000000ULL) + last->tv_usec)));
154 }
155
156 unsigned long simple_hash(const char *name)
@@ -386,7 +386,7 @@ struct config {
386 struct config *next;
387 } *config_root = NULL;
388
389 -struct config_value *config_value_create(struct config *co, char *name, char *value)
389 +struct config_value *config_value_create(struct config *co, const char *name, const char *value)
390 {
391 debug(D_CONFIG, "Creating config entry for name '%s', value '%s', in section '%s'.", name, value, co->name);
392
@@ -409,7 +409,7 @@ struct config_value *config_value_create(struct config *co, char *name, char *va
409 return cv;
410 }
411
412 -struct config *config_create(char *section)
412 +struct config *config_create(const char *section)
413 {
414 debug(D_CONFIG, "Creating section '%s'.", section);
415
@@ -431,7 +431,7 @@ struct config *config_create(char *section)
431 return co;
432 }
433
434 -struct config *config_find_section(char *section)
434 +struct config *config_find_section(const char *section)
435 {
436 struct config *co;
437 unsigned long hash = simple_hash(section);
@@ -549,7 +549,7 @@ int load_config(char *filename, int overwrite_used)
549 return 1;
550 }
551
552 -char *config_get(char *section, char *name, char *default_value)
552 +char *config_get(const char *section, const char *name, const char *default_value)
553 {
554 struct config_value *cv;
555
@@ -573,7 +573,7 @@ char *config_get(char *section, char *name, char *default_value)
573 return(cv->value);
574 }
575
576 -long long config_get_number(char *section, char *name, long long value)
576 +long long config_get_number(const char *section, const char *name, long long value)
577 {
578 char buffer[100], *s;
579 sprintf(buffer, "%lld", value);
@@ -582,7 +582,7 @@ long long config_get_number(char *section, char *name, long long value)
582 return strtoll(s, NULL, 0);
583 }
584
585 -int config_get_boolean(char *section, char *name, int value)
585 +int config_get_boolean(const char *section, const char *name, int value)
586 {
587 char *s;
588 if(value) s = "yes";
@@ -600,7 +600,7 @@ int config_get_boolean(char *section, char *name, int value)
600 }
601 }
602
603 -void config_set(char *section, char *name, char *value)
603 +void config_set(const char *section, const char *name, char *value)
604 {
605 struct config_value *cv;
606
@@ -626,7 +626,7 @@ void config_set(char *section, char *name, char *value)
626 pthread_mutex_unlock(&config_mutex);
627 }
628
629 -void config_set_number(char *section, char *name, long long value)
629 +void config_set_number(const char *section, const char *name, long long value)
630 {
631 char buffer[100];
632 sprintf(buffer, "%lld", value);
@@ -634,7 +634,7 @@ void config_set_number(char *section, char *name, long long value)
634 config_set(section, name, buffer);
635 }
636
637 -void config_set_boolean(char *section, char *name, int value)
637 +void config_set_boolean(const char *section, const char *name, int value)
638 {
639 char *s;
640 if(value) s = "yes";
@@ -644,6 +644,39 @@ void config_set_boolean(char *section, char *name, int value)
644 }
645
646
647 +// ----------------------------------------------------------------------------
648 +// chart types
649 +
650 +#define CHART_TYPE_LINE 0
651 +#define CHART_TYPE_AREA 1
652 +#define CHART_TYPE_STACKED 2
653 +
654 +int chart_type_id(const char *name)
655 +{
656 + if(strcmp(name, "area") == 0) return CHART_TYPE_AREA;
657 + if(strcmp(name, "stacked") == 0) return CHART_TYPE_STACKED;
658 + if(strcmp(name, "line") == 0) return CHART_TYPE_LINE;
659 + return CHART_TYPE_LINE;
660 +}
661 +
662 +const char *chart_type_name(int chart_type)
663 +{
664 + static char *line = "line";
665 + static char *area = "area";
666 + static char *stacked = "stacked";
667 +
668 + switch(chart_type) {
669 + case CHART_TYPE_LINE:
670 + return line;
671 +
672 + case CHART_TYPE_AREA:
673 + return area;
674 +
675 + case CHART_TYPE_STACKED:
676 + return stacked;
677 + }
678 + return line;
679 +}
680
681
682 // ----------------------------------------------------------------------------
@@ -651,6 +684,21 @@ void config_set_boolean(char *section, char *name, int value)
684
685 #define RRD_STATS_NAME_MAX 1024
686
687 +//typedef long double calculated_number;
688 +//#define CALCULATED_NUMBER_FORMAT "%0.1Lf"
689 +typedef long long calculated_number;
690 +#define CALCULATED_NUMBER_FORMAT "%lld"
691 +
692 +typedef long long collected_number;
693 +#define COLLECTED_NUMBER_FORMAT "%lld"
694 +
695 +typedef long long total_number;
696 +#define TOTAL_NUMBER_FORMAT "%lld"
697 +
698 +typedef int32_t storage_number;
699 +#define STORAGE_NUMBER_FORMAT "%d"
700 +
701 +
702 struct rrd_dimension {
703 char id[RRD_STATS_NAME_MAX + 1]; // the id of this dimension (for internal identification)
704 char name[RRD_STATS_NAME_MAX + 1]; // the name of this dimension (as presented to user)
@@ -667,15 +715,15 @@ struct rrd_dimension {
715 long multiplier;
716 long divisor;
717
670 - int32_t *values; // the array of values
718 + storage_number *values; // the array of values
719
720 struct timeval last_updated; // when was this dimension last updated
721
674 - long long calculated_value;
675 - long long last_calculated_value;
722 + calculated_number calculated_value;
723 + calculated_number last_calculated_value;
724
677 - long long collected_value;
678 - long long last_collected_value;
725 + collected_number collected_value;
726 + collected_number last_collected_value;
727
728 struct rrd_dimension *next; // linking of dimensions within the same data set
729 };
@@ -706,12 +754,15 @@ struct rrd_stats {
754 // it goes around in a round-robin fashion
755
756 int update_every; // every how many seconds is this updated?
757 + unsigned long long first_entry_t; // the timestamp (in microseconds) of the oldest entry in the db
758 struct timeval last_updated; // when this data set was last updated
759 unsigned long long usec_since_last_update;
760
712 - long long absolute_total;
713 - long long last_absolute_total;
761 + total_number absolute_total;
762 + total_number last_absolute_total;
763
764 + int chart_type;
765 + int debug;
766 int enabled;
767 int isdetail; // if set, the data set should be considered as a detail of another
768 // (the master data set should be the one that has the same family and is not detail)
@@ -726,7 +777,7 @@ typedef struct rrd_stats RRD_STATS;
777 RRD_STATS *root = NULL;
778 pthread_mutex_t root_mutex = PTHREAD_MUTEX_INITIALIZER;
779
729 -RRD_STATS *rrd_stats_create(const char *type, const char *id, const char *name, const char *family, const char *title, const char *units, long priority)
780 +RRD_STATS *rrd_stats_create(const char *type, const char *id, const char *name, const char *family, const char *title, const char *units, long priority, int update_every, int chart_type)
781 {
782 RRD_STATS *st = NULL;
783 char *p;
@@ -776,6 +827,8 @@ RRD_STATS *rrd_stats_create(const char *type, const char *id, const char *name,
827 snprintf(st->usertitle, RRD_STATS_NAME_MAX, "%s (%s)", st->title, st->name);
828 strncpy(st->usertitle, config_get(st->id, "title", st->usertitle), RRD_STATS_NAME_MAX);
829
830 + st->chart_type = chart_type_id(config_get(st->id, "chart type", chart_type_name(chart_type)));
831 +
832 p = config_get(st->id, "history", "default");
833 st->entries = strtoul(p, NULL, 0);
834 if(strcmp(p, "default") == 0) st->entries = save_history;
@@ -786,6 +839,8 @@ RRD_STATS *rrd_stats_create(const char *type, const char *id, const char *name,
839 st->enabled = config_get_boolean(st->id, "enabled", 1);
840 if(!st->enabled) st->entries = 5;
841
842 + st->debug = config_get_boolean(st->id, "debug", 0);
843 +
844 st->timediff = calloc(st->entries, sizeof(uint32_t));
845 if(!st->timediff) {
846 free(st);
@@ -825,7 +880,7 @@ RRD_DIMENSION *rrd_stats_dimension_add(RRD_STATS *st, const char *id, const char
880 rd->divisor = divisor;
881 rd->algorithm = algorithm;
882
828 - rd->values = calloc(rd->entries, sizeof(int32_t));
883 + rd->values = calloc(rd->entries, sizeof(storage_number));
884 if(!rd->values) {
885 free(rd);
886 fatal("Cannot allocate %lu entries for RRD_DIMENSION values.", rd->entries);
@@ -934,7 +989,7 @@ int rrd_stats_dimension_hide(RRD_STATS *st, const char *id)
989 return 0;
990 }
991
937 -void rrd_stats_dimension_set_by_pointer(RRD_STATS *st, RRD_DIMENSION *rd, long long value)
992 +void rrd_stats_dimension_set_by_pointer(RRD_STATS *st, RRD_DIMENSION *rd, collected_number value)
993 {
994 rd->last_updated.tv_sec = st->last_updated.tv_sec;
995 rd->last_updated.tv_usec = st->last_updated.tv_usec;
@@ -942,7 +997,7 @@ void rrd_stats_dimension_set_by_pointer(RRD_STATS *st, RRD_DIMENSION *rd, long l
997 rd->collected_value = value;
998 }
999
945 -int rrd_stats_dimension_set(RRD_STATS *st, char *id, long long value)
1000 +int rrd_stats_dimension_set(RRD_STATS *st, char *id, collected_number value)
1001 {
1002 RRD_DIMENSION *rd = rrd_stats_dimension_find(st, id);
1003 if(!rd) {
@@ -1006,6 +1061,12 @@ void rrd_stats_done(RRD_STATS *st)
1061 rd = rd->next;
1062 }
1063
1064 + if(!st->dimensions) {
1065 + st->enabled = 0;
1066 + // rrd_stats_free(st);
1067 + return;
1068 + }
1069 +
1070 // calculate totals and count the dimensions
1071 st->absolute_total = 0;
1072 int dimensions;
@@ -1019,39 +1080,144 @@ void rrd_stats_done(RRD_STATS *st)
1080 if(st->counter) {
1081
1082 st->usec_since_last_update = usecdiff(&now, &st->last_updated);
1083 + if(st->debug) debug(D_RRD_STATS, "microseconds since last update: %llu", st->usec_since_last_update);
1084 +
1085 + // x 10
1086 + // in all calculations we multiply with 10 to allow
1087 + // for all 1 decimal point at the chart
1088
1089 // process all dimensions to calculate its values
1090 for( rd = st->dimensions ; rd ; rd = rd->next ) {
1025 - rd->calculated_value = rd->collected_value;
1026 -
1091 switch(rd->algorithm) {
1092 case RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL:
1029 - rd->calculated_value = (100 * (rd->collected_value - rd->last_collected_value)) / (st->absolute_total - st->last_absolute_total);
1093 + // the percentage of the current increment
1094 + // over the increment of all dimensions together
1095 + rd->calculated_value =
1096 + (calculated_number)10
1097 + * (calculated_number)100
1098 + * (calculated_number)(rd->collected_value - rd->last_collected_value)
1099 + / (calculated_number)(st->absolute_total - st->last_absolute_total);
1100 +
1101 + if(st->debug)
1102 + debug(D_RRD_STATS, "%s/%s: CALC "
1103 + CALCULATED_NUMBER_FORMAT " = 10 * 100"
1104 + " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1105 + " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1106 + , st->id, rd->name
1107 + , rd->calculated_value
1108 + , rd->collected_value, rd->last_collected_value
1109 + , st->absolute_total, st->last_absolute_total
1110 + );
1111 break;
1112
1113 case RRD_DIMENSION_PCENT_OVER_ROW_TOTAL:
1033 - rd->calculated_value = (100 * rd->collected_value) / st->absolute_total;
1114 + // the percentage of the current value
1115 + // over the total of all dimensions
1116 + rd->calculated_value =
1117 + (calculated_number)10
1118 + * (calculated_number)100
1119 + * (calculated_number)rd->collected_value
1120 + / (calculated_number)st->absolute_total;
1121 +
1122 + if(st->debug)
1123 + debug(D_RRD_STATS, "%s/%s: CALC "
1124 + CALCULATED_NUMBER_FORMAT " = 10 * 100"
1125 + " * " COLLECTED_NUMBER_FORMAT
1126 + " / " COLLECTED_NUMBER_FORMAT
1127 + , st->id, rd->name
1128 + , rd->calculated_value
1129 + , rd->collected_value
1130 + , st->absolute_total
1131 + );
1132 break;
1133
1134 case RRD_DIMENSION_INCREMENTAL:
1135 + // we need the incremental calculation to produce per second results
1136 + // so, we multiply with 1.000.000 and divide by the microseconds passed since
1137 + // the last entry
1138 if(rd->last_collected_value > rd->collected_value) rd->calculated_value = 0;
1038 - else rd->calculated_value = rd->collected_value - rd->last_collected_value;
1139 + else rd->calculated_value =
1140 + (calculated_number)10
1141 + * (calculated_number)1000000
1142 + * (calculated_number)(rd->collected_value - rd->last_collected_value)
1143 + / (calculated_number)st->usec_since_last_update;
1144 +
1145 + if(st->debug)
1146 + debug(D_RRD_STATS, "%s/%s: CALC "
1147 + CALCULATED_NUMBER_FORMAT " = 10 * 1000000"
1148 + " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1149 + " / %llu"
1150 + , st->id, rd->name
1151 + , rd->calculated_value
1152 + , rd->collected_value, rd->last_collected_value
1153 + , st->usec_since_last_update
1154 + );
1155 + break;
1156
1040 - rd->calculated_value = (rd->calculated_value * 1000000) / st->usec_since_last_update;
1157 + case RRD_DIMENSION_ABSOLUTE:
1158 + rd->calculated_value =
1159 + (calculated_number)10
1160 + * (calculated_number)rd->collected_value;
1161 +
1162 + if(st->debug)
1163 + debug(D_RRD_STATS, "%s/%s: CALC "
1164 + CALCULATED_NUMBER_FORMAT " = 10"
1165 + " * " COLLECTED_NUMBER_FORMAT
1166 + , st->id, rd->name
1167 + , rd->calculated_value
1168 + , rd->collected_value
1169 + );
1170 break;
1171
1172 default:
1173 + // make the default zero, to make sure
1174 + // it gets noticed when we add new types
1175 + rd->calculated_value = 0;
1176 +
1177 + if(st->debug)
1178 + debug(D_RRD_STATS, "%s/%s: CALC "
1179 + CALCULATED_NUMBER_FORMAT " = 0"
1180 + , st->id, rd->name
1181 + , rd->calculated_value
1182 + );
1183 break;
1184 }
1185
1047 - rd->calculated_value = rd->calculated_value * 10 * rd->multiplier / rd->divisor;
1048 -
1186 // store the calculated value
1050 - rd->values[st->current_entry] = rd->calculated_value;
1187 + rd->values[st->current_entry] = (storage_number)
1188 + ( rd->calculated_value
1189 + * (calculated_number)rd->multiplier
1190 + / (calculated_number)rd->divisor
1191 + );
1192 +
1193 + if(st->debug)
1194 + debug(D_RRD_STATS, "%s/%s STORE "
1195 + STORAGE_NUMBER_FORMAT " = "
1196 + CALCULATED_NUMBER_FORMAT
1197 + " * %ld"
1198 + " / %ld"
1199 + , st->id, rd->name
1200 + , rd->values[st->current_entry]
1201 + , rd->calculated_value
1202 + , rd->multiplier
1203 + , rd->divisor
1204 + );
1205 }
1206
1053 - // store the time difference to the last entry
1054 - st->timediff[st->current_entry] = st->usec_since_last_update;
1207 + if(!st->first_entry_t) {
1208 + // this is the first entry in the database
1209 + st->first_entry_t = now.tv_sec * 1000000ULL + now.tv_usec;
1210 + }
1211 + else {
1212 + if(st->counter > st->entries) {
1213 + // the db is overwriting values
1214 + // add the value we will overwrite
1215 + st->first_entry_t += st->timediff[st->current_entry];
1216 + }
1217 +
1218 + // store the time difference to the last entry
1219 + st->timediff[st->current_entry] = st->usec_since_last_update;
1220 + }
1221 }
1222
1223 st->last_updated.tv_sec = now.tv_sec;
@@ -1243,16 +1409,9 @@ struct web_client *web_client_free(struct web_client *w)
1409 // find the oldest entry in the data, skipping all empty slots
1410 time_t rrd_stats_first_entry_t(RRD_STATS *st)
1411 {
1246 - unsigned long long usec = st->last_updated.tv_sec * 1000000 + st->last_updated.tv_usec;
1247 -
1248 - long t;
1249 - for( t = st->current_entry - 1 ; t != st->current_entry ; t--) {
1250 - if(t < 0) t = st->entries - 1;
1251 - if(!st->timediff[t]) break;
1252 - usec -= st->timediff[t];
1253 - }
1254 -
1255 - return(usec / 1000000);
1412 + if(!st->first_entry_t) return st->last_updated.tv_sec;
1413 +
1414 + return st->first_entry_t / 1000000;
1415 }
1416
1417 unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer *wb)
@@ -1261,8 +1420,6 @@ unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer
1420
1421 pthread_mutex_lock(&st->mutex);
1422
1264 - time_t first_entry_t = rrd_stats_first_entry_t(st);
1265 -
1423 web_buffer_printf(wb,
1424 "\t\t{\n"
1425 "\t\t\t\"id\": \"%s\",\n"
@@ -1274,16 +1431,18 @@ unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer
1431 "\t\t\t\"enabled\": %d,\n"
1432 "\t\t\t\"units\": \"%s\",\n"
1433 "\t\t\t\"url\": \"/data/%s/%s\",\n"
1434 + "\t\t\t\"chart_type\": \"%s\",\n"
1435 + "\t\t\t\"counter\": %ld,\n"
1436 "\t\t\t\"entries\": %ld,\n"
1278 - "\t\t\t\"first_entry_t\": %ld,\n"
1437 + "\t\t\t\"first_entry_t\": %lu,\n"
1438 "\t\t\t\"last_entry\": %ld,\n"
1439 "\t\t\t\"last_entry_t\": %lu,\n"
1440 "\t\t\t\"last_entry_secs_ago\": %lu,\n"
1441 "\t\t\t\"update_every\": %d,\n"
1442 "\t\t\t\"isdetail\": %d,\n"
1443 "\t\t\t\"usec_since_last_update\": %llu,\n"
1285 - "\t\t\t\"absolute_total\": %lld,\n"
1286 - "\t\t\t\"last_absolute_total\": %lld,\n"
1444 + "\t\t\t\"absolute_total\": " TOTAL_NUMBER_FORMAT ",\n"
1445 + "\t\t\t\"last_absolute_total\": " TOTAL_NUMBER_FORMAT ",\n"
1446 "\t\t\t\"dimensions\": [\n"
1447 , st->id
1448 , st->name
@@ -1294,8 +1453,10 @@ unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer
1453 , st->enabled
1454 , st->units
1455 , st->name, options?options:""
1456 + , chart_type_name(st->chart_type)
1457 + , st->counter
1458 , st->entries
1298 - , first_entry_t
1459 + , rrd_stats_first_entry_t(st)
1460 , st->current_entry
1461 , st->last_updated.tv_sec
1462 , time(NULL) - st->last_updated.tv_sec
@@ -1310,7 +1471,7 @@ unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer
1471
1472 RRD_DIMENSION *rd;
1473 for(rd = st->dimensions; rd ; rd = rd->next) {
1313 - unsigned long rdmem = sizeof(RRD_DIMENSION) + (sizeof(int32_t) * rd->entries);
1474 + unsigned long rdmem = sizeof(RRD_DIMENSION) + (sizeof(storage_number) * rd->entries);
1475 memory += rdmem;
1476
1477 char *algorithm = "";
@@ -1346,10 +1507,10 @@ unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer
1507 "\t\t\t\t\t\"multiplier\": %ld,\n"
1508 "\t\t\t\t\t\"divisor\": %ld,\n"
1509 "\t\t\t\t\t\"last_entry_t\": %lu,\n"
1349 - "\t\t\t\t\t\"collected_value\": %lld,\n"
1350 - "\t\t\t\t\t\"calculated_value\": %lld,\n"
1351 - "\t\t\t\t\t\"last_collected_value\": %lld,\n"
1352 - "\t\t\t\t\t\"last_calculated_value\": %lld,\n"
1510 + "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
1511 + "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
1512 + "\t\t\t\t\t\"last_collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
1513 + "\t\t\t\t\t\"last_calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
1514 "\t\t\t\t\t\"memory\": %lu\n"
1515 "\t\t\t\t}%s\n"
1516 , rd->id
@@ -1534,9 +1695,9 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1695 struct timeval now;
1696 now.tv_sec = st->last_updated.tv_sec;
1697 now.tv_usec = st->last_updated.tv_usec;
1537 - unsigned long long time_usec = now.tv_sec * 1000000 + now.tv_usec;
1698 + unsigned long long time_usec = now.tv_sec * 1000000ULL + now.tv_usec;
1699 long t, count;
1539 - for (count = printed = 0, t = current_entry; t != stop_entry ; time_usec -= st->timediff[t], t--) {
1700 + for (count = printed = 0, t = current_entry; t != stop_entry && st->timediff[t] ; time_usec -= st->timediff[t], t--) {
1701 int print_this = 0;
1702
1703 if(t < 0) t = st->entries - 1;
@@ -1546,6 +1707,7 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1707
1708 // make sure we return data in the proper time range
1709 if(now.tv_sec < after || now.tv_sec > before) continue;
1710 +
1711 count++;
1712 group_count++;
1713
@@ -2904,7 +3066,7 @@ int do_proc_net_dev() {
3066 if(do_bandwidth) {
3067 st = rrd_stats_find_bytype(RRD_TYPE_NET, iface);
3068 if(!st) {
2907 - st = rrd_stats_create(RRD_TYPE_NET, iface, NULL, iface, "Bandwidth", "kilobits/s", 1000);
3069 + st = rrd_stats_create(RRD_TYPE_NET, iface, NULL, iface, "Bandwidth", "kilobits/s", 1000, update_every, CHART_TYPE_AREA);
3070
3071 rrd_stats_dimension_add(st, "received", NULL, 8, 1024, RRD_DIMENSION_INCREMENTAL);
3072 rrd_stats_dimension_add(st, "sent", NULL, -8, 1024, RRD_DIMENSION_INCREMENTAL);
@@ -2921,7 +3083,7 @@ int do_proc_net_dev() {
3083 if(do_packets) {
3084 st = rrd_stats_find_bytype("net_packets", iface);
3085 if(!st) {
2924 - st = rrd_stats_create("net_packets", iface, NULL, iface, "Packets", "packets/s", 1001);
3086 + st = rrd_stats_create("net_packets", iface, NULL, iface, "Packets", "packets/s", 1001, update_every, CHART_TYPE_LINE);
3087 st->isdetail = 1;
3088
3089 rrd_stats_dimension_add(st, "received", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -2939,7 +3101,7 @@ int do_proc_net_dev() {
3101 if(do_errors) {
3102 st = rrd_stats_find_bytype("net_errors", iface);
3103 if(!st) {
2942 - st = rrd_stats_create("net_errors", iface, NULL, iface, "Interface Errors", "errors/s", 1002);
3104 + st = rrd_stats_create("net_errors", iface, NULL, iface, "Interface Errors", "errors/s", 1002, update_every, CHART_TYPE_LINE);
3105 st->isdetail = 1;
3106
3107 rrd_stats_dimension_add(st, "receive", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -2957,7 +3119,7 @@ int do_proc_net_dev() {
3119 if(do_fifo) {
3120 st = rrd_stats_find_bytype("net_fifo", iface);
3121 if(!st) {
2960 - st = rrd_stats_create("net_fifo", iface, NULL, iface, "Interface Queue", "packets", 1100);
3122 + st = rrd_stats_create("net_fifo", iface, NULL, iface, "Interface Queue", "packets", 1100, update_every, CHART_TYPE_LINE);
3123 st->isdetail = 1;
3124
3125 rrd_stats_dimension_add(st, "receive", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
@@ -2975,7 +3137,7 @@ int do_proc_net_dev() {
3137 if(do_compressed) {
3138 st = rrd_stats_find_bytype("net_compressed", iface);
3139 if(!st) {
2978 - st = rrd_stats_create("net_compressed", iface, NULL, iface, "Compressed Packets", "packets/s", 1200);
3140 + st = rrd_stats_create("net_compressed", iface, NULL, iface, "Compressed Packets", "packets/s", 1200, update_every, CHART_TYPE_LINE);
3141 st->isdetail = 1;
3142
3143 rrd_stats_dimension_add(st, "received", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3193,7 +3355,7 @@ int do_proc_diskstats() {
3355 }
3356 else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
3357
3196 - st = rrd_stats_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000);
3358 + st = rrd_stats_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, CHART_TYPE_AREA);
3359
3360 rrd_stats_dimension_add(st, "reads", NULL, sector_size, 1024, RRD_DIMENSION_INCREMENTAL);
3361 rrd_stats_dimension_add(st, "writes", NULL, sector_size * -1, 1024, RRD_DIMENSION_INCREMENTAL);
@@ -3210,7 +3372,7 @@ int do_proc_diskstats() {
3372 if(do_ops) {
3373 st = rrd_stats_find_bytype("disk_ops", disk);
3374 if(!st) {
3213 - st = rrd_stats_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001);
3375 + st = rrd_stats_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, CHART_TYPE_LINE);
3376 st->isdetail = 1;
3377
3378 rrd_stats_dimension_add(st, "reads", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3228,7 +3390,7 @@ int do_proc_diskstats() {
3390 if(do_merged_ops) {
3391 st = rrd_stats_find_bytype("disk_merged_ops", disk);
3392 if(!st) {
3231 - st = rrd_stats_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010);
3393 + st = rrd_stats_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, CHART_TYPE_LINE);
3394 st->isdetail = 1;
3395
3396 rrd_stats_dimension_add(st, "reads", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3246,7 +3408,7 @@ int do_proc_diskstats() {
3408 if(do_iotime) {
3409 st = rrd_stats_find_bytype("disk_iotime", disk);
3410 if(!st) {
3249 - st = rrd_stats_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005);
3411 + st = rrd_stats_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, CHART_TYPE_LINE);
3412 st->isdetail = 1;
3413
3414 rrd_stats_dimension_add(st, "reads", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3268,7 +3430,7 @@ int do_proc_diskstats() {
3430 if(do_cur_ops) {
3431 st = rrd_stats_find_bytype("disk_cur_ops", disk);
3432 if(!st) {
3271 - st = rrd_stats_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004);
3433 + st = rrd_stats_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, CHART_TYPE_LINE);
3434 st->isdetail = 1;
3435
3436 rrd_stats_dimension_add(st, "operations", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
@@ -3343,7 +3505,7 @@ int do_proc_net_snmp() {
3505 if(do_ip_packets) {
3506 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".packets");
3507 if(!st) {
3346 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "packets", NULL, RRD_TYPE_NET_SNMP, "IPv4 Packets", "packets/s", 3000);
3508 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "packets", NULL, RRD_TYPE_NET_SNMP, "IPv4 Packets", "packets/s", 3000, update_every, CHART_TYPE_LINE);
3509
3510 rrd_stats_dimension_add(st, "received", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
3511 rrd_stats_dimension_add(st, "sent", NULL, -1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3362,7 +3524,7 @@ int do_proc_net_snmp() {
3524 if(do_ip_fragsout) {
3525 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".fragsout");
3526 if(!st) {
3365 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "fragsout", NULL, RRD_TYPE_NET_SNMP, "IPv4 Fragments Sent", "packets/s", 3010);
3527 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "fragsout", NULL, RRD_TYPE_NET_SNMP, "IPv4 Fragments Sent", "packets/s", 3010, update_every, CHART_TYPE_LINE);
3528 st->isdetail = 1;
3529
3530 rrd_stats_dimension_add(st, "ok", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3382,7 +3544,7 @@ int do_proc_net_snmp() {
3544 if(do_ip_fragsin) {
3545 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".fragsin");
3546 if(!st) {
3385 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "fragsin", NULL, RRD_TYPE_NET_SNMP, "IPv4 Fragments Reassembly", "packets/s", 3011);
3547 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "fragsin", NULL, RRD_TYPE_NET_SNMP, "IPv4 Fragments Reassembly", "packets/s", 3011, update_every, CHART_TYPE_LINE);
3548 st->isdetail = 1;
3549
3550 rrd_stats_dimension_add(st, "ok", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3402,7 +3564,7 @@ int do_proc_net_snmp() {
3564 if(do_ip_errors) {
3565 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".errors");
3566 if(!st) {
3405 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "errors", NULL, RRD_TYPE_NET_SNMP, "IPv4 Errors", "packets/s", 3002);
3567 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "errors", NULL, RRD_TYPE_NET_SNMP, "IPv4 Errors", "packets/s", 3002, update_every, CHART_TYPE_LINE);
3568 st->isdetail = 1;
3569
3570 rrd_stats_dimension_add(st, "InDiscards", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3450,7 +3612,7 @@ int do_proc_net_snmp() {
3612 if(do_tcp_sockets) {
3613 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcpsock");
3614 if(!st) {
3453 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", "IPv4 TCP Connections", "active connections", 2500);
3615 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", "IPv4 TCP Connections", "active connections", 2500, update_every, CHART_TYPE_LINE);
3616
3617 rrd_stats_dimension_add(st, "connections", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
3618 }
@@ -3465,7 +3627,7 @@ int do_proc_net_snmp() {
3627 if(do_tcp_packets) {
3628 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcppackets");
3629 if(!st) {
3468 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", "IPv4 TCP Packets", "packets/s", 2600);
3630 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", "IPv4 TCP Packets", "packets/s", 2600, update_every, CHART_TYPE_LINE);
3631
3632 rrd_stats_dimension_add(st, "received", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
3633 rrd_stats_dimension_add(st, "sent", NULL, -1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3482,7 +3644,7 @@ int do_proc_net_snmp() {
3644 if(do_tcp_errors) {
3645 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcperrors");
3646 if(!st) {
3485 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", "IPv4 TCP Errors", "packets/s", 2700);
3647 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", "IPv4 TCP Errors", "packets/s", 2700, update_every, CHART_TYPE_LINE);
3648 st->isdetail = 1;
3649
3650 rrd_stats_dimension_add(st, "InErrs", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3500,7 +3662,7 @@ int do_proc_net_snmp() {
3662 if(do_tcp_handshake) {
3663 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcphandshake");
3664 if(!st) {
3503 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", "IPv4 TCP Handshake Issues", "events/s", 2900);
3665 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", "IPv4 TCP Handshake Issues", "events/s", 2900, update_every, CHART_TYPE_LINE);
3666 st->isdetail = 1;
3667
3668 rrd_stats_dimension_add(st, "EstabResets", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3543,7 +3705,7 @@ int do_proc_net_snmp() {
3705 if(do_udp_packets) {
3706 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".udppackets");
3707 if(!st) {
3546 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", "IPv4 UDP Packets", "packets/s", 2601);
3708 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", "IPv4 UDP Packets", "packets/s", 2601, update_every, CHART_TYPE_LINE);
3709
3710 rrd_stats_dimension_add(st, "received", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
3711 rrd_stats_dimension_add(st, "sent", NULL, -1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3560,7 +3722,7 @@ int do_proc_net_snmp() {
3722 if(do_udp_errors) {
3723 st = rrd_stats_find(RRD_TYPE_NET_SNMP ".udperrors");
3724 if(!st) {
3563 - st = rrd_stats_create(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", "IPv4 UDP Errors", "events/s", 2701);
3725 + st = rrd_stats_create(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", "IPv4 UDP Errors", "events/s", 2701, update_every, CHART_TYPE_LINE);
3726 st->isdetail = 1;
3727
3728 rrd_stats_dimension_add(st, "RcvbufErrors", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3640,7 +3802,7 @@ int do_proc_net_netstat() {
3802 if(do_bandwidth) {
3803 st = rrd_stats_find("system.ipv4");
3804 if(!st) {
3643 - st = rrd_stats_create("system", "ipv4", NULL, "ipv4", "IPv4 Bandwidth", "kilobits/s", 2000);
3805 + st = rrd_stats_create("system", "ipv4", NULL, "ipv4", "IPv4 Bandwidth", "kilobits/s", 2000, update_every, CHART_TYPE_AREA);
3806
3807 rrd_stats_dimension_add(st, "received", NULL, 8, 1024, RRD_DIMENSION_INCREMENTAL);
3808 rrd_stats_dimension_add(st, "sent", NULL, -8, 1024, RRD_DIMENSION_INCREMENTAL);
@@ -3657,7 +3819,7 @@ int do_proc_net_netstat() {
3819 if(do_inerrors) {
3820 st = rrd_stats_find("ipv4.inerrors");
3821 if(!st) {
3660 - st = rrd_stats_create("ipv4", "inerrors", NULL, "ipv4", "IPv4 Input Errors", "packets/s", 4000);
3822 + st = rrd_stats_create("ipv4", "inerrors", NULL, "ipv4", "IPv4 Input Errors", "packets/s", 4000, update_every, CHART_TYPE_LINE);
3823 st->isdetail = 1;
3824
3825 rrd_stats_dimension_add(st, "noroutes", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3675,7 +3837,7 @@ int do_proc_net_netstat() {
3837 if(do_mcast) {
3838 st = rrd_stats_find("ipv4.mcast");
3839 if(!st) {
3678 - st = rrd_stats_create("ipv4", "mcast", NULL, "ipv4", "IPv4 Multicast Bandwidth", "kilobits/s", 9000);
3840 + st = rrd_stats_create("ipv4", "mcast", NULL, "ipv4", "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, CHART_TYPE_AREA);
3841 st->isdetail = 1;
3842
3843 rrd_stats_dimension_add(st, "received", NULL, 8, 1024, RRD_DIMENSION_INCREMENTAL);
@@ -3693,7 +3855,7 @@ int do_proc_net_netstat() {
3855 if(do_bcast) {
3856 st = rrd_stats_find("ipv4.bcast");
3857 if(!st) {
3696 - st = rrd_stats_create("ipv4", "bcast", NULL, "ipv4", "IPv4 Broadcast Bandwidth", "kilobits/s", 8000);
3858 + st = rrd_stats_create("ipv4", "bcast", NULL, "ipv4", "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, CHART_TYPE_AREA);
3859 st->isdetail = 1;
3860
3861 rrd_stats_dimension_add(st, "received", NULL, 8, 1024, RRD_DIMENSION_INCREMENTAL);
@@ -3711,7 +3873,7 @@ int do_proc_net_netstat() {
3873 if(do_mcast_p) {
3874 st = rrd_stats_find("ipv4.mcastpkts");
3875 if(!st) {
3714 - st = rrd_stats_create("ipv4", "mcastpkts", NULL, "ipv4", "IPv4 Multicast Packets", "packets/s", 9500);
3876 + st = rrd_stats_create("ipv4", "mcastpkts", NULL, "ipv4", "IPv4 Multicast Packets", "packets/s", 9500, update_every, CHART_TYPE_LINE);
3877 st->isdetail = 1;
3878
3879 rrd_stats_dimension_add(st, "received", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3729,7 +3891,7 @@ int do_proc_net_netstat() {
3891 if(do_bcast_p) {
3892 st = rrd_stats_find("ipv4.bcastpkts");
3893 if(!st) {
3732 - st = rrd_stats_create("ipv4", "bcastpkts", NULL, "ipv4", "IPv4 Broadcast Packets", "packets/s", 8500);
3894 + st = rrd_stats_create("ipv4", "bcastpkts", NULL, "ipv4", "IPv4 Broadcast Packets", "packets/s", 8500, update_every, CHART_TYPE_LINE);
3895 st->isdetail = 1;
3896
3897 rrd_stats_dimension_add(st, "received", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3817,7 +3979,7 @@ int do_proc_net_stat_conntrack() {
3979 if(do_sockets) {
3980 st = rrd_stats_find(RRD_TYPE_NET_STAT_CONNTRACK ".sockets");
3981 if(!st) {
3820 - st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Connections", "active connections", 1000);
3982 + st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Connections", "active connections", 1000, update_every, CHART_TYPE_LINE);
3983
3984 rrd_stats_dimension_add(st, "connections", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
3985 }
@@ -3832,7 +3994,7 @@ int do_proc_net_stat_conntrack() {
3994 if(do_new) {
3995 st = rrd_stats_find(RRD_TYPE_NET_STAT_CONNTRACK ".new");
3996 if(!st) {
3835 - st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter New Connections", "connections/s", 1001);
3997 + st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter New Connections", "connections/s", 1001, update_every, CHART_TYPE_LINE);
3998
3999 rrd_stats_dimension_add(st, "new", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
4000 rrd_stats_dimension_add(st, "ignore", NULL, -1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3851,7 +4013,7 @@ int do_proc_net_stat_conntrack() {
4013 if(do_changes) {
4014 st = rrd_stats_find(RRD_TYPE_NET_STAT_CONNTRACK ".changes");
4015 if(!st) {
3854 - st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Connection Changes", "changes/s", 1002);
4016 + st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Connection Changes", "changes/s", 1002, update_every, CHART_TYPE_LINE);
4017 st->isdetail = 1;
4018
4019 rrd_stats_dimension_add(st, "inserted", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3871,7 +4033,7 @@ int do_proc_net_stat_conntrack() {
4033 if(do_expect) {
4034 st = rrd_stats_find(RRD_TYPE_NET_STAT_CONNTRACK ".expect");
4035 if(!st) {
3874 - st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Connection Expectations", "expectations/s", 1003);
4036 + st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Connection Expectations", "expectations/s", 1003, update_every, CHART_TYPE_LINE);
4037 st->isdetail = 1;
4038
4039 rrd_stats_dimension_add(st, "created", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3891,7 +4053,7 @@ int do_proc_net_stat_conntrack() {
4053 if(do_search) {
4054 st = rrd_stats_find(RRD_TYPE_NET_STAT_CONNTRACK ".search");
4055 if(!st) {
3894 - st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Connection Searches", "searches/s", 1010);
4056 + st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Connection Searches", "searches/s", 1010, update_every, CHART_TYPE_LINE);
4057 st->isdetail = 1;
4058
4059 rrd_stats_dimension_add(st, "searched", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3911,7 +4073,7 @@ int do_proc_net_stat_conntrack() {
4073 if(do_errors) {
4074 st = rrd_stats_find(RRD_TYPE_NET_STAT_CONNTRACK ".errors");
4075 if(!st) {
3914 - st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Errors", "events/s", 1005);
4076 + st = rrd_stats_create(RRD_TYPE_NET_STAT_CONNTRACK, "errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, "Netfilter Errors", "events/s", 1005, update_every, CHART_TYPE_LINE);
4077 st->isdetail = 1;
4078
4079 rrd_stats_dimension_add(st, "icmp_error", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -3987,7 +4149,7 @@ int do_proc_net_ip_vs_stats() {
4149 if(do_sockets) {
4150 st = rrd_stats_find(RRD_TYPE_NET_IPVS ".sockets");
4151 if(!st) {
3990 - st = rrd_stats_create(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, "IPVS New Connections", "connections/s", 1001);
4152 + st = rrd_stats_create(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, "IPVS New Connections", "connections/s", 1001, update_every, CHART_TYPE_LINE);
4153
4154 rrd_stats_dimension_add(st, "connections", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
4155 }
@@ -4002,7 +4164,7 @@ int do_proc_net_ip_vs_stats() {
4164 if(do_packets) {
4165 st = rrd_stats_find(RRD_TYPE_NET_IPVS ".packets");
4166 if(!st) {
4005 - st = rrd_stats_create(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, "IPVS Packets", "packets/s", 1002);
4167 + st = rrd_stats_create(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, "IPVS Packets", "packets/s", 1002, update_every, CHART_TYPE_LINE);
4168
4169 rrd_stats_dimension_add(st, "received", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
4170 rrd_stats_dimension_add(st, "sent", NULL, -1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -4019,7 +4181,7 @@ int do_proc_net_ip_vs_stats() {
4181 if(do_bandwidth) {
4182 st = rrd_stats_find(RRD_TYPE_NET_IPVS ".net");
4183 if(!st) {
4022 - st = rrd_stats_create(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, "IPVS Bandwidth", "kilobits/s", 1000);
4184 + st = rrd_stats_create(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, "IPVS Bandwidth", "kilobits/s", 1000, update_every, CHART_TYPE_AREA);
4185
4186 rrd_stats_dimension_add(st, "received", NULL, 8, 1024, RRD_DIMENSION_INCREMENTAL);
4187 rrd_stats_dimension_add(st, "sent", NULL, -8, 1024, RRD_DIMENSION_INCREMENTAL);
@@ -4083,7 +4245,7 @@ int do_proc_stat() {
4245 if((isthistotal && do_cpu) || (!isthistotal && do_cpu_cores)) {
4246 st = rrd_stats_find_bytype(type, id);
4247 if(!st) {
4086 - st = rrd_stats_create(type, id, NULL, "cpu", title, "percentage", priority);
4248 + st = rrd_stats_create(type, id, NULL, "cpu", title, "percentage", priority, update_every, CHART_TYPE_STACKED);
4249
4250 long multiplier = 1;
4251 long divisor = 1; // sysconf(_SC_CLK_TCK);
@@ -4130,7 +4292,7 @@ int do_proc_stat() {
4292 if(do_interrupts) {
4293 st = rrd_stats_find_bytype("system", id);
4294 if(!st) {
4133 - st = rrd_stats_create("system", id, NULL, "cpu", "CPU Interrupts", "interrupts/s", 900);
4295 + st = rrd_stats_create("system", id, NULL, "cpu", "CPU Interrupts", "interrupts/s", 900, update_every, CHART_TYPE_LINE);
4296 st->isdetail = 1;
4297
4298 rrd_stats_dimension_add(st, "interrupts", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -4155,7 +4317,7 @@ int do_proc_stat() {
4317 if(do_context) {
4318 st = rrd_stats_find_bytype("system", id);
4319 if(!st) {
4158 - st = rrd_stats_create("system", id, NULL, "cpu", "CPU Context Switches", "context switches/s", 800);
4320 + st = rrd_stats_create("system", id, NULL, "cpu", "CPU Context Switches", "context switches/s", 800, update_every, CHART_TYPE_LINE);
4321
4322 rrd_stats_dimension_add(st, "switches", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
4323 }
@@ -4206,7 +4368,7 @@ int do_proc_stat() {
4368 if(do_forks) {
4369 st = rrd_stats_find_bytype("system", "forks");
4370 if(!st) {
4209 - st = rrd_stats_create("system", "forks", NULL, "cpu", "New Processes", "processes/s", 700);
4371 + st = rrd_stats_create("system", "forks", NULL, "cpu", "New Processes", "processes/s", 700, update_every, CHART_TYPE_LINE);
4372 st->isdetail = 1;
4373
4374 rrd_stats_dimension_add(st, "started", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -4222,7 +4384,7 @@ int do_proc_stat() {
4384 if(do_processes) {
4385 st = rrd_stats_find_bytype("system", "processes");
4386 if(!st) {
4225 - st = rrd_stats_create("system", "processes", NULL, "cpu", "Processes", "processes", 600);
4387 + st = rrd_stats_create("system", "processes", NULL, "cpu", "Processes", "processes", 600, update_every, CHART_TYPE_LINE);
4388
4389 rrd_stats_dimension_add(st, "running", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
4390 rrd_stats_dimension_add(st, "blocked", NULL, -1, 1, RRD_DIMENSION_ABSOLUTE);
@@ -4343,7 +4505,7 @@ int do_proc_meminfo() {
4505 if(do_ram) {
4506 st = rrd_stats_find("system.ram");
4507 if(!st) {
4346 - st = rrd_stats_create("system", "ram", NULL, "mem", "System RAM", "MB", 200);
4508 + st = rrd_stats_create("system", "ram", NULL, "mem", "System RAM", "MB", 200, update_every, CHART_TYPE_STACKED);
4509
4510 rrd_stats_dimension_add(st, "buffers", NULL, 1, 1024, RRD_DIMENSION_ABSOLUTE);
4511 rrd_stats_dimension_add(st, "used", NULL, 1, 1024, RRD_DIMENSION_ABSOLUTE);
@@ -4366,7 +4528,7 @@ int do_proc_meminfo() {
4528 if(do_swap) {
4529 st = rrd_stats_find("system.swap");
4530 if(!st) {
4369 - st = rrd_stats_create("system", "swap", NULL, "mem", "System Swap", "MB", 201);
4531 + st = rrd_stats_create("system", "swap", NULL, "mem", "System Swap", "MB", 201, update_every, CHART_TYPE_STACKED);
4532 st->isdetail = 1;
4533
4534 rrd_stats_dimension_add(st, "free", NULL, 1, 1024, RRD_DIMENSION_ABSOLUTE);
@@ -4384,7 +4546,7 @@ int do_proc_meminfo() {
4546 if(hwcorrupted && do_hwcorrupt) {
4547 st = rrd_stats_find("mem.hwcorrupt");
4548 if(!st) {
4387 - st = rrd_stats_create("mem", "hwcorrupt", NULL, "mem", "Hardware Corrupted ECC", "MB", 9000);
4549 + st = rrd_stats_create("mem", "hwcorrupt", NULL, "mem", "Hardware Corrupted ECC", "MB", 9000, update_every, CHART_TYPE_LINE);
4550 st->isdetail = 1;
4551
4552 rrd_stats_dimension_add(st, "HardwareCorrupted", NULL, 1, 1024, RRD_DIMENSION_ABSOLUTE);
@@ -4400,7 +4562,7 @@ int do_proc_meminfo() {
4562 if(do_committed) {
4563 st = rrd_stats_find("mem.committed");
4564 if(!st) {
4403 - st = rrd_stats_create("mem", "committed", NULL, "mem", "Committed (Allocated) Memory", "MB", 5000);
4565 + st = rrd_stats_create("mem", "committed", NULL, "mem", "Committed (Allocated) Memory", "MB", 5000, update_every, CHART_TYPE_AREA);
4566 st->isdetail = 1;
4567
4568 rrd_stats_dimension_add(st, "Committed_AS", NULL, 1, 1024, RRD_DIMENSION_ABSOLUTE);
@@ -4416,7 +4578,7 @@ int do_proc_meminfo() {
4578 if(do_writeback) {
4579 st = rrd_stats_find("mem.writeback");
4580 if(!st) {
4419 - st = rrd_stats_create("mem", "writeback", NULL, "mem", "Writeback Memory", "MB", 4000);
4581 + st = rrd_stats_create("mem", "writeback", NULL, "mem", "Writeback Memory", "MB", 4000, update_every, CHART_TYPE_LINE);
4582 st->isdetail = 1;
4583
4584 rrd_stats_dimension_add(st, "Dirty", NULL, 1, 1024, RRD_DIMENSION_ABSOLUTE);
@@ -4440,7 +4602,7 @@ int do_proc_meminfo() {
4602 if(do_kernel) {
4603 st = rrd_stats_find("mem.kernel");
4604 if(!st) {
4443 - st = rrd_stats_create("mem", "kernel", NULL, "mem", "Memory Used by Kernel", "MB", 6000);
4605 + st = rrd_stats_create("mem", "kernel", NULL, "mem", "Memory Used by Kernel", "MB", 6000, update_every, CHART_TYPE_STACKED);
4606 st->isdetail = 1;
4607
4608 rrd_stats_dimension_add(st, "Slab", NULL, 1, 1024, RRD_DIMENSION_ABSOLUTE);
@@ -4462,7 +4624,7 @@ int do_proc_meminfo() {
4624 if(do_slab) {
4625 st = rrd_stats_find("mem.slab");
4626 if(!st) {
4465 - st = rrd_stats_create("mem", "slab", NULL, "mem", "Reclaimable Kernel Memory", "MB", 6500);
4627 + st = rrd_stats_create("mem", "slab", NULL, "mem", "Reclaimable Kernel Memory", "MB", 6500, update_every, CHART_TYPE_STACKED);
4628 st->isdetail = 1;
4629
4630 rrd_stats_dimension_add(st, "reclaimable", NULL, 1, 1024, RRD_DIMENSION_ABSOLUTE);
@@ -4630,7 +4792,7 @@ int do_proc_vmstat() {
4792 if(do_swapio) {
4793 st = rrd_stats_find("system.swapio");
4794 if(!st) {
4633 - st = rrd_stats_create("system", "swapio", NULL, "mem", "Swap I/O", "kilobytes/s", 250);
4795 + st = rrd_stats_create("system", "swapio", NULL, "mem", "Swap I/O", "kilobytes/s", 250, update_every, CHART_TYPE_AREA);
4796
4797 rrd_stats_dimension_add(st, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_DIMENSION_INCREMENTAL);
4798 rrd_stats_dimension_add(st, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_DIMENSION_INCREMENTAL);
@@ -4647,7 +4809,7 @@ int do_proc_vmstat() {
4809 if(do_io) {
4810 st = rrd_stats_find("system.io");
4811 if(!st) {
4650 - st = rrd_stats_create("system", "io", NULL, "disk", "Disk I/O", "kilobytes/s", 150);
4812 + st = rrd_stats_create("system", "io", NULL, "disk", "Disk I/O", "kilobytes/s", 150, update_every, CHART_TYPE_AREA);
4813
4814 rrd_stats_dimension_add(st, "in", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
4815 rrd_stats_dimension_add(st, "out", NULL, -1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -4664,7 +4826,7 @@ int do_proc_vmstat() {
4826 if(do_pgfaults) {
4827 st = rrd_stats_find("system.pgfaults");
4828 if(!st) {
4667 - st = rrd_stats_create("system", "pgfaults", NULL, "mem", "Memory Page Faults", "page faults/s", 500);
4829 + st = rrd_stats_create("system", "pgfaults", NULL, "mem", "Memory Page Faults", "page faults/s", 500, update_every, CHART_TYPE_LINE);
4830 st->isdetail = 1;
4831
4832 rrd_stats_dimension_add(st, "minor", NULL, 1, 1, RRD_DIMENSION_INCREMENTAL);
@@ -4732,7 +4894,7 @@ void *proc_main(void *ptr)
4894 usec = usecdiff(&now, &last) - susec;
4895 debug(D_PROCNETDEV_LOOP, "PROCNETDEV: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec);
4896
4735 - if(usec < (update_every * 1000000)) susec = (update_every * 1000000) - usec;
4897 + if(usec < (update_every * 1000000ULL)) susec = (update_every * 1000000ULL) - usec;
4898 else susec = 0;
4899
4900 // make sure we will wait at least 100ms
@@ -4742,12 +4904,12 @@ void *proc_main(void *ptr)
4904
4905 if(!vdo_cpu_netdata && getrusage(RUSAGE_SELF, &me) == 0) {
4906
4745 - unsigned long long cpuuser = me.ru_utime.tv_sec * 1000000L + me.ru_utime.tv_usec;
4746 - unsigned long long cpusyst = me.ru_stime.tv_sec * 1000000L + me.ru_stime.tv_usec;
4907 + unsigned long long cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec;
4908 + unsigned long long cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec;
4909
4910 if(!stcpu) stcpu = rrd_stats_find("cpu.netdata");
4911 if(!stcpu) {
4750 - stcpu = rrd_stats_create("cpu", "netdata", NULL, "cpu", "NetData CPU usage", "milliseconds/s", 9999);
4912 + stcpu = rrd_stats_create("cpu", "netdata", NULL, "cpu", "NetData CPU usage", "milliseconds/s", 9999, update_every, CHART_TYPE_STACKED);
4913
4914 rrd_stats_dimension_add(stcpu, "user", NULL, 1, 1000, RRD_DIMENSION_INCREMENTAL);
4915 rrd_stats_dimension_add(stcpu, "system", NULL, 1, 1000, RRD_DIMENSION_INCREMENTAL);
@@ -4845,7 +5007,7 @@ void tc_device_commit(struct tc_device *d)
5007 if(!st) {
5008 debug(D_TC_LOOP, "TC: Committing new TC device '%s'", d->name);
5009
4848 - st = rrd_stats_create(RRD_TYPE_TC, d->id, d->name, d->family, "Class Usage", "kilobits/s", 1000);
5010 + st = rrd_stats_create(RRD_TYPE_TC, d->id, d->name, d->family, "Class Usage", "kilobits/s", 1000, update_every, CHART_TYPE_STACKED);
5011
5012 for ( c = d->classes ; c ; c = c->next) {
5013 if(c->isleaf && c->hasparent)
@@ -5089,7 +5251,7 @@ void *cpuidlejitter_main(void *ptr)
5251 while(1) {
5252 unsigned long long usec = 0, susec = 0;
5253
5092 - while(susec < (update_every * 1000000L)) {
5254 + while(susec < (update_every * 1000000ULL)) {
5255
5256 gettimeofday(&before, NULL);
5257 usleep(sleep_ms * 1000);
@@ -5103,7 +5265,7 @@ void *cpuidlejitter_main(void *ptr)
5265
5266 RRD_STATS *st = rrd_stats_find("system.idlejitter");
5267 if(!st) {
5106 - st = rrd_stats_create("system", "idlejitter", NULL, "cpu", "CPU Idle Jitter", "microseconds lost/s", 9999);
5268 + st = rrd_stats_create("system", "idlejitter", NULL, "cpu", "CPU Idle Jitter", "microseconds lost/s", 9999, update_every, CHART_TYPE_LINE);
5269
5270 rrd_stats_dimension_add(st, "jitter", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
5271 }
web/netdata.js
+27 -45
@@ -248,51 +248,33 @@ function loadCharts(base_url, doNext) {
248 };
249
250 // set the chart type
251 - if(json.charts[i].type == "tc"
252 - || json.charts[i].id.substring(0, 7) == "cpu.cpu"
253 - || json.charts[i].name == 'system.cpu'
254 - || json.charts[i].name == 'system.ram'
255 - || json.charts[i].name == 'system.swap'
256 - || json.charts[i].name == 'mem.slab'
257 - || json.charts[i].name == 'mem.kernel'
258 - || json.charts[i].name == 'cpu.netdata'
259 - ) {
260 -
261 - // default for all stacked AreaChart
262 - json.charts[i].chartType = "AreaChart";
263 - json.charts[i].chartOptions.isStacked = true;
264 - json.charts[i].chartOptions.areaOpacity = 0.85;
265 - json.charts[i].chartOptions.lineWidth = 1;
266 -
267 - if(json.charts[i].name == 'system.swap')
268 - json.charts[i].chartOptions.vAxis.viewWindowMode = 'maximized';
269 -
270 - json.charts[i].group_method = "average";
271 - }
272 - else if(json.charts[i].type == "net"
273 - || json.charts[i].type == "disk"
274 - || json.charts[i].id == "system.ipv4"
275 - || json.charts[i].id == "system.io"
276 - || json.charts[i].id == "system.swapio"
277 - || json.charts[i].id == "ipv4.mcast"
278 - || json.charts[i].id == "ipv4.bcast"
279 - || json.charts[i].id == "mem.committed"
280 - ) {
281 -
282 - // default for all AreaChart
283 - json.charts[i].chartType = "AreaChart";
284 - json.charts[i].chartOptions.isStacked = false;
285 - json.charts[i].chartOptions.areaOpacity = 0.3;
286 - }
287 - else {
288 -
289 - // default for all LineChart
290 - json.charts[i].chartType = "LineChart";
291 - json.charts[i].chartOptions.lineWidth = 2;
292 - json.charts[i].chartOptions.curveType = 'function';
293 -
294 - json.charts[i].chartOptions.vAxis.minValue = -0.1;
295 - json.charts[i].chartOptions.vAxis.maxValue = 0.1;
251 + switch(json.charts[i].chart_type) {
252 + case "area":
253 + json.charts[i].chartType = "AreaChart";
254 + json.charts[i].chartOptions.isStacked = false;
255 + json.charts[i].chartOptions.areaOpacity = 0.3;
256 + break;
257 +
258 + case "stacked":
259 + json.charts[i].chartType = "AreaChart";
260 + json.charts[i].chartOptions.isStacked = true;
261 + json.charts[i].chartOptions.areaOpacity = 0.85;
262 + json.charts[i].chartOptions.lineWidth = 1;
263 + json.charts[i].group_method = "average";
264 +
265 + if(json.charts[i].name == 'system.swap')
266 + json.charts[i].chartOptions.vAxis.viewWindowMode = 'maximized';
267 + break;
268 +
269 + default:
270 + case "line":
271 + json.charts[i].chartType = "LineChart";
272 + json.charts[i].chartOptions.lineWidth = 2;
273 + json.charts[i].chartOptions.curveType = 'function';
274 +
275 + json.charts[i].chartOptions.vAxis.minValue = -0.1;
276 + json.charts[i].chartOptions.vAxis.maxValue = 0.1;
277 + break;
278 }
279
280 // the category name, and other options, per type