@cryptotaxi247 / netdata-1 / commits / 9d7f91737

added netdata info at the footer, added cpu.netdata chart, added memory consumption info all.json

Costa Tsaousis (ktsaou) committed Apr 26, 2014 at 01:05 UTC 9d7f917378d208d26095484b7d3bf247006dd8da
4 files changed +134 -38
netdata.c
+100 -20
@@ -108,6 +108,9 @@
108 //#define DEBUG 0xffffffff
109 //#define DEBUG (0)
110
111 +#define HOSTNAME_MAX 1024
112 +char hostname[HOSTNAME_MAX + 1];
113 +
114 unsigned long long debug_flags = DEBUG;
115 char *debug_log = NULL;
116 int debug_fd = -1;
@@ -390,8 +393,6 @@ struct rrd_stats {
393 char envtitle[RRD_STATS_NAME_MAX + 1]; // the variable name for taking the title
394 char envpriority[RRD_STATS_NAME_MAX + 1]; // the variable name for taking the priority
395
393 - char hostname[RRD_STATS_NAME_MAX + 1]; // the host this data set belongs to
394 -
396 size_t entries; // total number of entries in the data set
397 size_t current_entry; // the entry that is currently being updated
398 // it goes around in a round-robin fashion
@@ -484,9 +485,6 @@ RRD_STATS *rrd_stats_create(const char *type, const char *id, const char *name,
485 if(p) strncpy(st->userpriority, p, RRD_STATS_NAME_MAX);
486 else strncpy(st->userpriority, st->name, RRD_STATS_NAME_MAX);
487
487 - if(gethostname(st->hostname, RRD_STATS_NAME_MAX) == -1)
488 - error("Cannot get hostname.");
489 -
488 st->entries = entries;
489 st->current_entry = 0;
490 // st->last_entry = 0;
@@ -965,7 +963,7 @@ size_t rrd_stats_first_entry(RRD_STATS *st)
963 return first_entry;
964 }
965
968 -void rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer *wb)
966 +unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer *wb)
967 {
968 web_buffer_increase(wb, 16384);
969
@@ -987,22 +985,70 @@ void rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer *wb)
985 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"usertitle\" : \"%s %s (%s)\",\n", st->title, st->usertitle, st->name);
986
987 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"userpriority\" : \"%s\",\n", st->userpriority);
990 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"envtitle\" : \"%s\",\n", st->envtitle);
991 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"envpriority\" : \"%s\",\n", st->envpriority);
992 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"hostname\" : \"%s\",\n", st->hostname);
988 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"envtitle\" : \"%s\",\n", st->envtitle);
989 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"envpriority\" : \"%s\",\n", st->envpriority);
990 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"units\" : \"%s\",\n", st->units);
991 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"url\" : \"/data/%s/%s\",\n", st->name, options?options:"");
992 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"entries\" : %ld,\n", st->entries);
996 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"first_entry\" : %ld,\n", first_entry);
993 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"first_entry\" : %ld,\n", first_entry);
994 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"first_entry_t\" : %ld,\n", first_entry_t);
998 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"last_entry\" : %ld,\n", st->current_entry);
995 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"last_entry\" : %ld,\n", st->current_entry);
996 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"last_entry_t\" : %lu,\n", st->last_updated);
1000 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"last_entry_secs_ago\" : %lu,\n", time(NULL) - st->last_updated);
997 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"last_entry_secs_ago\" : %lu,\n", time(NULL) - st->last_updated);
998 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"update_every\" : %d,\n", update_every);
1002 - wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"isdetail\" : %d\n", st->isdetail);
999 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"isdetail\" : %d,\n", st->isdetail);
1000 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"dimensions\" : [\n");
1001 +
1002 + unsigned long memory = sizeof(RRD_STATS) + (sizeof(struct timeval) * st->entries);
1003 +
1004 + RRD_DIMENSION *rd;
1005 + for(rd = st->dimensions; rd ; rd = rd->next) {
1006 + unsigned long rdmem = sizeof(RRD_DIMENSION) + (rd->bytes * rd->entries);
1007 + memory += rdmem;
1008 +
1009 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t{\n");
1010 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"id\" : \"%s\",\n", rd->id);
1011 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"name\" : \"%s\",\n", rd->name);
1012 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"bytes\" : %ld,\n", rd->bytes);
1013 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"entries\" : %ld,\n", rd->entries);
1014 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"isSigned\" : %d,\n", rd->issigned);
1015 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"isHidden\" : %d,\n", rd->hidden);
1016 +
1017 + switch(rd->type) {
1018 + case RRD_DIMENSION_INCREMENTAL:
1019 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : \"%s\",\n", "incremental");
1020 + break;
1021 +
1022 + case RRD_DIMENSION_ABSOLUTE:
1023 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : \"%s\",\n", "absolute");
1024 + break;
1025 +
1026 + case RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL:
1027 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : \"%s\",\n", "percent on incremental total");
1028 + break;
1029 +
1030 + case RRD_DIMENSION_PCENT_OVER_ROW_TOTAL:
1031 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : \"%s\",\n", "percent on absolute total");
1032 + break;
1033 +
1034 + default:
1035 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"type\" : %d,\n", rd->type);
1036 + break;
1037 + }
1038 +
1039 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"multiplier\" : %ld,\n", rd->multiplier);
1040 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"divisor\" : %ld,\n", rd->divisor);
1041 + //wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"last_entry_t\" : %lu,\n", rd->last_updated);
1042 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t\t\"memory\" : %lu\n", rdmem);
1043 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\t}%s\n", rd->next?",":"");
1044 + }
1045 +
1046 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t],\n");
1047 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t\t\"memory\" : %lu\n", memory);
1048 wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\t}");
1049
1050 pthread_mutex_unlock(&st->mutex);
1051 + return memory;
1052 }
1053
1054 #define RRD_GRAPH_JSON_HEADER "{\n\t\"charts\": [\n"
@@ -1019,8 +1065,9 @@ void rrd_stats_graph_json(RRD_STATS *st, char *options, struct web_buffer *wb)
1065
1066 void rrd_stats_all_json(struct web_buffer *wb)
1067 {
1022 - web_buffer_increase(wb, 16384);
1068 + web_buffer_increase(wb, 150000);
1069
1070 + unsigned long memory = 0;
1071 size_t c;
1072 RRD_STATS *st;
1073
@@ -1028,10 +1075,15 @@ void rrd_stats_all_json(struct web_buffer *wb)
1075
1076 for(st = root, c = 0; st ; st = st->next, c++) {
1077 if(c) wb->bytes += sprintf(&wb->buffer[wb->bytes], "%s", ",\n");
1031 - rrd_stats_one_json(st, NULL, wb);
1078 + memory += rrd_stats_one_json(st, NULL, wb);
1079 }
1080
1034 - wb->bytes += sprintf(&wb->buffer[wb->bytes], RRD_GRAPH_JSON_FOOTER);
1081 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n\t],\n");
1082 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\"hostname\": \"%s\",\n", hostname);
1083 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\"update_every\": %d,\n", update_every);
1084 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\"history\": %d,\n", save_history);
1085 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "\t\"memory\": %lu\n", memory);
1086 + wb->bytes += sprintf(&wb->buffer[wb->bytes], "}\n");
1087 }
1088
1089 long double rrd_stats_dimension_get(RRD_DIMENSION *rd, size_t position)
@@ -4074,7 +4126,7 @@ int do_proc_vmstat() {
4126 st->isdetail = 1;
4127
4128 rrd_stats_dimension_add(st, "minor", NULL, sizeof(unsigned long long), 0, 1, 1, RRD_DIMENSION_INCREMENTAL, NULL);
4077 - rrd_stats_dimension_add(st, "major", NULL, sizeof(unsigned long long), 0, 1, 1, RRD_DIMENSION_INCREMENTAL, NULL);
4129 + rrd_stats_dimension_add(st, "major", NULL, sizeof(unsigned long long), 0, -1, 1, RRD_DIMENSION_INCREMENTAL, NULL);
4130 }
4131 else rrd_stats_next(st);
4132
@@ -4090,6 +4142,7 @@ int do_proc_vmstat() {
4142
4143 void *proc_main(void *ptr)
4144 {
4145 + struct rusage me, me_last;
4146 struct timeval last, now;
4147
4148 gettimeofday(&last, NULL);
@@ -4106,7 +4159,11 @@ void *proc_main(void *ptr)
4159 int vdo_proc_meminfo = 0;
4160 int vdo_proc_vmstat = 0;
4161
4162 + RRD_STATS *stcpu = NULL;
4163 +
4164 gettimeofday(&last, NULL);
4165 + getrusage(RUSAGE_SELF, &me_last);
4166 +
4167 unsigned long long usec = 0, susec = 0;
4168 for(;1;) {
4169
@@ -4122,6 +4179,8 @@ void *proc_main(void *ptr)
4179 if(!vdo_proc_vmstat) vdo_proc_vmstat = do_proc_vmstat(usec);
4180 // END -- the job is done
4181
4182 + getrusage(RUSAGE_SELF, &me);
4183 +
4184 // find the time to sleep in order to wait exactly update_every seconds
4185 gettimeofday(&now, NULL);
4186 usec = usecdiff(&now, &last) - susec;
@@ -4133,11 +4192,29 @@ void *proc_main(void *ptr)
4192 // make sure we will wait at least 100ms
4193 if(susec < 100000) susec = 100000;
4194
4195 + // --------------------------------------------------------------------
4196 +
4197 + unsigned long long cpuuser = usecdiff(&me.ru_utime, &me_last.ru_utime) * (usec + susec) / (update_every * 1000000);
4198 + unsigned long long cpusyst = usecdiff(&me.ru_stime, &me_last.ru_stime) * (usec + susec) / (update_every * 1000000);
4199 +
4200 + if(!stcpu) stcpu = rrd_stats_find("cpu.netdata");
4201 + if(!stcpu) {
4202 + stcpu = rrd_stats_create("cpu", "netdata", NULL, "cpu", "NetData CPU usage", "milliseconds/s", save_history);
4203 +
4204 + rrd_stats_dimension_add(stcpu, "user", NULL, sizeof(unsigned long long), 0, 1, 1000, RRD_DIMENSION_ABSOLUTE, NULL);
4205 + rrd_stats_dimension_add(stcpu, "system", NULL, sizeof(unsigned long long), 0, 1, 1000, RRD_DIMENSION_ABSOLUTE, NULL);
4206 + }
4207 + else rrd_stats_next(stcpu);
4208 +
4209 + rrd_stats_dimension_set(stcpu, "user", &cpuuser, NULL);
4210 + rrd_stats_dimension_set(stcpu, "system", &cpusyst, NULL);
4211 + rrd_stats_done(stcpu);
4212 +
4213 usleep(susec);
4214
4138 - // copy now to last
4139 - last.tv_sec = now.tv_sec;
4140 - last.tv_usec = now.tv_usec;
4215 + // copy current to last
4216 + bcopy(&me, &me_last, sizeof(struct rusage));
4217 + bcopy(&now, &last, sizeof(struct timeval));
4218 }
4219
4220 return NULL;
@@ -4665,6 +4742,9 @@ int main(int argc, char **argv)
4742 }
4743 }
4744
4745 + if(gethostname(hostname, HOSTNAME_MAX) == -1)
4746 + error("WARNING: Cannot get machine hostname.");
4747 +
4748 // never become a problem
4749 if(nice(20) == -1) {
4750 fprintf(stderr, "Cannot lower my CPU priority. Error: %s.\n", strerror(errno));
web/index.html
+3 -1
@@ -139,7 +139,9 @@
139 Distributed under GPL.
140 <p/>
141 (c) 2014 Costa Tsaousis <a href="mailto:costa@tsaousis.gr">costa@tsaousis.gr</a>
142 - </div>
142 + <p/>
143 + <div id="server_summary_id"></div>
144 + </div>
145
146 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
147 <script type='text/javascript'>
web/index.js
+8 -11
@@ -32,13 +32,6 @@ var mainmenu = "";
32 // ------------------------------------------------------------------------
33 // common HTML generation
34
35 -function chartIsLoadingHTML(name, 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 " + name + "<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
36 -
37 -function showChartIsLoading(id, name, width, height) {
38 - //mylog('adding loading chart html in div with id ' + id);
39 - document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height);
40 -}
41 -
35 function thumbChartActions(i, c, nogroup) {
36 var name = c.name;
37 if(!nogroup) name = c.group_tag;
@@ -841,8 +834,8 @@ function initCharts() {
834 var width = thumbWidth();
835 var height = TARGET_THUMB_GRAPH_HEIGHT;
836
844 - loadCharts(null, function(c) {
845 - mycharts = c;
837 + loadCharts(null, function(all) {
838 + mycharts = all.charts;
839
840 if(mycharts == null || mycharts.length == 0) {
841 alert("Cannot load data from server.");
@@ -857,12 +850,14 @@ function initCharts() {
850
851 mycharts.sort(chartssort);
852
860 - document.getElementById('hostname_id').innerHTML = mycharts[0].hostname;
861 - document.title = mycharts[0].hostname;
853 + document.getElementById('hostname_id').innerHTML = all.hostname;
854 + document.title = all.hostname;
855
856 // create an array for grouping all same-type graphs together
857 + var dimensions = 0;
858 var categories = new Array();
859 $.each(mycharts, function(i, c) {
860 + dimensions += c.dimensions.length;
861 c.chartOptions.width = width;
862 c.chartOptions.height = height;
863
@@ -893,6 +888,8 @@ function initCharts() {
888 }
889 });
890
891 + document.getElementById('server_summary_id').innerHTML = "<small>NetData server at <b>" + all.hostname + "</b> is maintaining <b>" + mycharts.length + "</b> charts, having <b>" + dimensions + "</b> dimensions of <b>" + all.history + "</b> entries each, which are updated every <b>" + all.update_every + "s</b>, using a total of <b>" + (Math.round(all.memory * 10 / 1024 / 1024) / 10) + " MB</b> for the round robbin database.</small>";
892 +
893 $.each(categories, function(i, a) {
894 if(a.name == "system") a.priority = 1;
895 else if(a.name == "net") a.priority = 2;
web/netdata.js
+23 -6
@@ -80,6 +80,14 @@ function refreshChart(chart, doNext) {
80 }
81 else console.log('Cannot create chart for ' + chart.url);
82 })
83 + .fail(function() {
84 + // to avoid an infinite loop, let's assume it was refreshed
85 + if(chart.chart) chart.chart.clearChart();
86 + chart.chart = null;
87 + chart.refreshCount = 0;
88 + showChartIsLoading(chart.div, chart.name, chart.chartOptions.width, chart.chartOptions.height, "failed to refresh");
89 + chart.last_updated = new Date().getTime();
90 + })
91 .always(function() {
92 if(typeof doNext == "function") doNext();
93 });
@@ -87,6 +95,14 @@ function refreshChart(chart, doNext) {
95 return true;
96 }
97
98 +function chartIsLoadingHTML(name, width, height, message)
99 +{
100 + return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\" style=\"vertical-align:middle\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading " + name + "<br/><br/><span class=\"label label-default\">" + (message?message:"Please wait...") + "</span></h4></td></tr></table>";
101 +}
102 +
103 +function showChartIsLoading(id, name, width, height, message) {
104 + document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height, message);
105 +}
106
107 // calculateChartPointsToShow
108 // calculate the chart group and point to show properties.
@@ -245,6 +261,7 @@ function loadCharts(base_url, doNext) {
261 || json.charts[i].name == 'system.swap'
262 || json.charts[i].name == 'mem.slab'
263 || json.charts[i].name == 'mem.kernel'
264 + || json.charts[i].name == 'cpu.netdata'
265 ) {
266
267 // default for all stacked AreaChart
@@ -252,7 +269,7 @@ function loadCharts(base_url, doNext) {
269 json.charts[i].chartOptions.isStacked = true;
270 json.charts[i].chartOptions.areaOpacity = 0.85;
271 json.charts[i].chartOptions.lineWidth = 1;
255 - json.charts[i].chartOptions.vAxis.viewWindowMode = 'maximized';
272 + //json.charts[i].chartOptions.vAxis.viewWindowMode = 'maximized';
273
274 json.charts[i].group_method = "average";
275 }
@@ -278,8 +295,8 @@ function loadCharts(base_url, doNext) {
295 json.charts[i].chartOptions.lineWidth = 2;
296 json.charts[i].chartOptions.curveType = 'function';
297
281 - json.charts[i].chartOptions.vAxis.minValue = -10;
282 - json.charts[i].chartOptions.vAxis.maxValue = 10;
298 + json.charts[i].chartOptions.vAxis.minValue = -0.1;
299 + json.charts[i].chartOptions.vAxis.maxValue = 0.1;
300 }
301
302 // the category name, and other options, per type
@@ -294,8 +311,8 @@ function loadCharts(base_url, doNext) {
311 json.charts[i].chartOptions.vAxis.maxValue = 100;
312 }
313 else {
297 - json.charts[i].chartOptions.vAxis.minValue = -10;
298 - json.charts[i].chartOptions.vAxis.maxValue = 10;
314 + json.charts[i].chartOptions.vAxis.minValue = -0.1;
315 + json.charts[i].chartOptions.vAxis.maxValue = 0.1;
316 }
317 break;
318
@@ -365,7 +382,7 @@ function loadCharts(base_url, doNext) {
382 }
383 });
384
368 - if(typeof doNext == "function") doNext(json.charts);
385 + if(typeof doNext == "function") doNext(json);
386 })
387 .fail(function() {
388 if(typeof doNext == "function") doNext();