added API option percentage to return the percentage of each dimension against the sum of all dimensions; added easypiecharts for system values
Costa Tsaousis (ktsaou) committed
Jan 8, 2016 at 02:52 UTC
0bf086e577fa1ff42f227c48da15d3cbfaf1580a
7 files changed
+404
-102
src/rrd2json.c
+94
-20
@@ -371,6 +371,11 @@ void rrdr_disable_not_selected_dimensions(RRDR *r, const char *dims)
371
for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
372
if(!strcmp(d->name, tok)) {
373
r->od[c] &= ~RRDR_HIDDEN;
374
+
375
+ // since the user needs this dimension
376
+ // make it appear as NONZERO, to return it
377
+ // even if the dimension has only zeros
378
+ r->od[c] |= RRDR_NONZERO;
379
}
380
}
381
}
@@ -425,22 +430,31 @@ void rrdr_buffer_print_format(BUFFER *wb, uint32_t format)
430
}
431
}
432
428
-uint32_t rrdr_check_options(RRDR *r, uint32_t options)
433
+uint32_t rrdr_check_options(RRDR *r, uint32_t options, const char *dims)
434
{
435
if(options & RRDR_OPTION_NONZERO) {
431
- long c, i;
432
- RRDDIM *rd;
433
-
434
- // find how many dimensions are not zero
435
- for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
436
- if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
437
- if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
438
- i++;
436
+ long i;
437
+
438
+ if(dims && *dims) {
439
+ // the caller wants specific dimensions
440
+ // disable NONZERO option
441
+ // to make sure we don't accidentally prevent
442
+ // the specific dimensions from being returned
443
+ i = 0;
444
+ }
445
+ else {
446
+ // find how many dimensions are not zero
447
+ long c;
448
+ RRDDIM *rd;
449
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
450
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
451
+ if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
452
+ i++;
453
+ }
454
}
455
441
- // if with nonzero we get i = 0
442
- // but c != 0, then disable nonzero
443
- // to show all dimensions
456
+ // if with nonzero we get i = 0 (no dimensions will be returned)
457
+ // disable nonzero to show all dimensions
458
if(!i) options &= ~RRDR_OPTION_NONZERO;
459
}
460
@@ -749,6 +763,7 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
763
}
764
765
// for each line in the array
766
+ calculated_number total = 1;
767
for(i = start; i != end ;i += step) {
768
calculated_number *cn = &r->v[ i * r->d ];
769
uint8_t *co = &r->o[ i * r->d ];
@@ -802,6 +817,20 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
817
buffer_strcat(wb, post_date);
818
}
819
820
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
821
+ total = 0;
822
+ for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
823
+ calculated_number n = cn[c];
824
+
825
+ if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
826
+ n = -n;
827
+
828
+ total += n;
829
+ }
830
+ // prevent a division by zero
831
+ if(total == 0) total = 1;
832
+ }
833
+
834
// for each dimension
835
for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
836
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
@@ -820,10 +849,15 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
849
else
850
buffer_strcat(wb, "null");
851
}
823
- else if((options & RRDR_OPTION_ABSOLUTE))
824
- buffer_rrd_value(wb, (n<0)?-n:n);
825
- else
852
+ else {
853
+ if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
854
+ n = -n;
855
+
856
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE))
857
+ n = n * 100 / total;
858
+
859
buffer_rrd_value(wb, n);
860
+ }
861
862
buffer_strcat(wb, post_value);
863
}
@@ -873,6 +907,7 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
907
}
908
909
// for each line in the array
910
+ calculated_number total = 1;
911
for(i = start; i != end ;i += step) {
912
calculated_number *cn = &r->v[ i * r->d ];
913
uint8_t *co = &r->o[ i * r->d ];
@@ -895,6 +930,20 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
930
buffer_date(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
931
}
932
933
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
934
+ total = 0;
935
+ for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
936
+ calculated_number n = cn[c];
937
+
938
+ if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
939
+ n = -n;
940
+
941
+ total += n;
942
+ }
943
+ // prevent a division by zero
944
+ if(total == 0) total = 1;
945
+ }
946
+
947
// for each dimension
948
for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
949
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
@@ -910,10 +959,15 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
959
else
960
buffer_strcat(wb, "null");
961
}
913
- else if((options & RRDR_OPTION_ABSOLUTE))
914
- buffer_rrd_value(wb, (n<0)?-n:n);
915
- else
962
+ else {
963
+ if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
964
+ n = -n;
965
+
966
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE))
967
+ n = n * 100 / total;
968
+
969
buffer_rrd_value(wb, n);
970
+ }
971
}
972
973
buffer_strcat(wb, endline);
@@ -936,6 +990,7 @@ static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix,
990
}
991
992
// for each line in the array
993
+ calculated_number total = 1;
994
for(i = start; i != end ;i += step) {
995
996
calculated_number *cn = &r->v[ i * r->d ];
@@ -944,6 +999,20 @@ static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix,
999
calculated_number sum = 0, min = 0, max = 0, v;
1000
int all_null = 1, init = 1;
1001
1002
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
1003
+ total = 0;
1004
+ for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
1005
+ calculated_number n = cn[c];
1006
+
1007
+ if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
1008
+ n = -n;
1009
+
1010
+ total += n;
1011
+ }
1012
+ // prevent a division by zero
1013
+ if(total == 0) total = 1;
1014
+ }
1015
+
1016
// for each dimension
1017
for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
1018
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
@@ -951,6 +1020,12 @@ static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix,
1020
1021
calculated_number n = cn[c];
1022
1023
+ if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
1024
+ n = -n;
1025
+
1026
+ if(unlikely(options & RRDR_OPTION_PERCENTAGE))
1027
+ n = n * 100 / total;
1028
+
1029
if(unlikely(init)) {
1030
if(n > 0) {
1031
min = 0;
@@ -965,7 +1040,6 @@ static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix,
1040
1041
if(likely(!(co[c] & RRDR_EMPTY))) {
1042
all_null = 0;
968
- if((options & RRDR_OPTION_ABSOLUTE) && n < 0) n = -n;
1043
sum += n;
1044
}
1045
@@ -1423,7 +1497,7 @@ int rrd2format(RRDSET *st, BUFFER *wb, BUFFER *dimensions, uint32_t format, long
1497
return 500;
1498
}
1499
1426
- options = rrdr_check_options(r, options);
1500
+ options = rrdr_check_options(r, options, (dimensions)?buffer_tostring(dimensions):NULL);
1501
1502
if(dimensions)
1503
rrdr_disable_not_selected_dimensions(r, buffer_tostring(dimensions));
src/rrd2json.h
+2
-1
@@ -42,7 +42,7 @@ extern char *hostname;
42
#define RRDR_OPTION_NONZERO 0x00000001 // don't output dimensions will just zero values
43
#define RRDR_OPTION_REVERSED 0x00000002 // output the rows in reverse order (oldest to newest)
44
#define RRDR_OPTION_ABSOLUTE 0x00000004 // values positive, for DATASOURCE_SSV before summing
45
-#define RRDR_OPTION_MIN2MAX 0x00000008 // for DATASOURCE_SSV, out max - min
45
+#define RRDR_OPTION_MIN2MAX 0x00000008 // for DATASOURCE_SSV, out max - min, instead of sum
46
#define RRDR_OPTION_SECONDS 0x00000010 // output seconds, instead of dates
47
#define RRDR_OPTION_MILLISECONDS 0x00000020 // output milliseconds, instead of dates
48
#define RRDR_OPTION_NULL2ZERO 0x00000040 // do not show nulls, convert them to zeros
@@ -50,6 +50,7 @@ extern char *hostname;
50
#define RRDR_OPTION_GOOGLE_JSON 0x00000100 // comply with google JSON/JSONP specs
51
#define RRDR_OPTION_JSON_WRAP 0x00000200 // wrap the response in a JSON header with info about the result
52
#define RRDR_OPTION_LABEL_QUOTES 0x00000400 // in CSV output, wrap header labels in double quotes
53
+#define RRDR_OPTION_PERCENTAGE 0x00000800 // give values as percentage of total
54
55
extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb);
56
extern void rrd_stats_api_v1_charts(BUFFER *wb);
src/web_client.c
+2
@@ -431,6 +431,8 @@ uint32_t web_client_api_request_v1_data_options(char *o)
431
ret |= RRDR_OPTION_OBJECTSROWS;
432
else if(!strcmp(tok, "google_json"))
433
ret |= RRDR_OPTION_GOOGLE_JSON;
434
+ else if(!strcmp(tok, "percentage"))
435
+ ret |= RRDR_OPTION_PERCENTAGE;
436
}
437
438
return ret;
web/dashboard.css
+1
-1
@@ -73,7 +73,7 @@ html {
73
}
74
75
.netdata-message.icon {
76
- color: #FAFAFA;
76
+ color: #F8F8F8;
77
text-align: center;
78
vertical-align: middle;
79
}
web/dashboard.js
+132
-78
@@ -377,12 +377,12 @@
377
if(NETDATA.options.debug.main_loop === true)
378
console.log('welcome to NETDATA');
379
380
- window.onresize = function(event) {
381
- NETDATA.options.last_page_scroll = new Date().getTime();
380
+ NETDATA.onresize = function() {
381
NETDATA.options.last_resized = new Date().getTime();
382
+ NETDATA.onscroll();
383
};
384
385
- window.onscroll = function(event) {
385
+ NETDATA.onscroll = function() {
386
NETDATA.options.last_page_scroll = new Date().getTime();
387
if(NETDATA.options.targets === null) return;
388
@@ -393,7 +393,10 @@
393
var targets = NETDATA.options.targets;
394
var len = targets.length;
395
while(len--) targets[len].isVisible();
396
- }
396
+ };
397
+
398
+ window.onresize = NETDATA.onresize;
399
+ window.onscroll = NETDATA.onscroll;
400
401
// ----------------------------------------------------------------------------------------------------------------
402
// Error Handling
@@ -900,6 +903,8 @@
903
this.chart = null; // object - the chart as downloaded from the server
904
905
this.title = self.data('title') || null; // the title of the chart
906
+ this.units = self.data('units') || null; // the units of the chart dimensions
907
+ this.append_options = self.data('append-options') || null; // the units of the chart dimensions
908
909
this.validated = false; // boolean - has the chart been validated?
910
this.enabled = true; // boolean - is the chart enabled for refresh?
@@ -1004,11 +1009,15 @@
1009
}
1010
that.element_legend_childs.series = null;
1011
1007
- if(that.width !== 0)
1012
+ if(typeof(that.width) === 'string')
1013
$(that.element).css('width', that.width);
1014
+ else if(typeof(that.width) === 'number')
1015
+ $(that.element).css('width', that.width + 'px');
1016
1010
- if(that.height !== 0)
1017
+ if(typeof(that.height) === 'string')
1018
$(that.element).css('height', that.height);
1019
+ else if(typeof(that.height) === 'number')
1020
+ $(that.element).css('height', that.height + 'px');
1021
1022
if(NETDATA.chartDefaults.min_width !== null)
1023
$(that.element).css('min-width', NETDATA.chartDefaults.min_width);
@@ -1140,36 +1149,71 @@
1149
1150
// hide the chart, when it is not visible - called from isVisible()
1151
var hideChart = function() {
1143
- // no chart yet
1144
- if(that.chart_created === false) return;
1152
+ // hide it, if it is not already hidden
1153
+ if(typeof that.___chartIsHidden___ !== 'undefined')
1154
+ return;
1155
1156
// we should destroy it
1157
if(NETDATA.options.current.destroy_on_hide === true) {
1148
- init();
1149
- that.___chartIsHidden___ = undefined;
1150
- return;
1158
+ if(that.chart_created === true) init();
1159
}
1152
-
1153
- // just hide it, if it is not already hidden
1154
- if(typeof that.___chartIsHidden___ === 'undefined') {
1160
+ else {
1161
showRendering();
1162
that.element_chart.style.display = 'none';
1163
if(that.element_legend !== null) that.element_legend.style.display = 'none';
1158
- that.___chartIsHidden___ = true;
1164
}
1165
+
1166
+ that.___chartIsHidden___ = true;
1167
}
1168
1169
// unhide the chart, when it is visible - called from isVisible()
1170
var unhideChart = function() {
1164
- if(typeof that.___chartIsHidden___ !== 'undefined') {
1171
+ if(typeof that.___chartIsHidden___ === 'undefined')
1172
+ return;
1173
+
1174
+ that.___chartIsHidden___ = undefined;
1175
+
1176
+ if(that.chart_created === false) {
1177
+ // we need to re-initialize it, to show our background
1178
+ // logo in bootstrap tabs, until the chart loads
1179
+ init();
1180
+ }
1181
+ else {
1182
that.element_chart.style.display = 'inline-block';
1183
if(that.element_legend !== null) that.element_legend.style.display = 'inline-block';
1167
- that.___chartIsHidden___ = undefined;
1184
resizeChart();
1185
hideMessage();
1186
}
1187
}
1188
1189
+ // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
1190
+ var callChartLibraryUpdateSafely = function(data) {
1191
+ var status;
1192
+
1193
+ try {
1194
+ status = that.library.update(that, data);
1195
+ }
1196
+ catch(err) {
1197
+ status = false;
1198
+ }
1199
+
1200
+ return status;
1201
+ }
1202
+
1203
+ // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
1204
+ var callChartLibraryCreateSafely = function(data) {
1205
+ var status;
1206
+
1207
+ try {
1208
+ status = that.library.create(that, data);
1209
+ }
1210
+ catch(err) {
1211
+ status = false;
1212
+ }
1213
+
1214
+ return status;
1215
+ }
1216
+
1217
// ----------------------------------------------------------------------------------------------------------------
1218
// Chart Resize
1219
@@ -1178,12 +1222,11 @@
1222
// a properly sized dom is available
1223
var resizeChart = function() {
1224
if(that.isVisible() === true && that.tm.last_resized < NETDATA.options.last_resized) {
1181
- that.tm.last_resized = new Date().getTime();
1225
if(that.chart_created === false) return;
1226
1184
- if(that.needsRecreation())
1227
+ if(that.needsRecreation()) {
1228
init();
1186
-
1229
+ }
1230
else if(typeof that.library.resize === 'function') {
1231
that.library.resize(that);
1232
@@ -1192,6 +1235,8 @@
1235
1236
maxMessageFontSize();
1237
}
1238
+
1239
+ that.tm.last_resized = new Date().getTime();
1240
}
1241
}
1242
@@ -1690,7 +1735,7 @@
1735
this.element_legend_childs.title_time.innerHTML = d.toLocaleTimeString();
1736
1737
if(this.element_legend_childs.title_units)
1693
- this.element_legend_childs.title_units.innerHTML = this.chart.units;
1738
+ this.element_legend_childs.title_units.innerHTML = this.units;
1739
}
1740
1741
this.legendShowUndefined = function() {
@@ -2096,6 +2141,9 @@
2141
if(NETDATA.options.current.eliminate_zero_dimensions === true)
2142
this.data_url += '|nonzero';
2143
2144
+ if(this.append_options !== null)
2145
+ this.data_url += '|' + this.append_options.toString();
2146
+
2147
if(after)
2148
this.data_url += "&after=" + after.toString();
2149
@@ -2184,22 +2232,17 @@
2232
if(this.debug === true)
2233
this.log('updating chart...');
2234
2187
- this.updates_since_last_creation++;
2188
- if(NETDATA.options.debug.chart_errors === true) {
2235
+ if(NETDATA.options.debug.chart_errors === true)
2236
status = this.library.update(this, data);
2237
+ else
2238
+ status = callChartLibraryUpdateSafely(data);
2239
+
2240
+ if(status === false) {
2241
+ error('chart failed to be updated as ' + this.library_name);
2242
}
2243
else {
2192
- try {
2193
- status = this.library.update(this, data);
2194
- }
2195
- catch(err) {
2196
- status = false;
2197
- error('chart failed to be updated as ' + this.library_name);
2198
- }
2244
+ this.updates_since_last_creation++;
2245
}
2200
-
2201
- if(status === false)
2202
- error('chart failed to be created as ' + this.library_name);
2246
}
2247
else {
2248
var status = false;
@@ -2207,25 +2250,18 @@
2250
if(this.debug === true)
2251
this.log('creating chart...');
2252
2210
- if(NETDATA.options.debug.chart_errors === true) {
2253
+ if(NETDATA.options.debug.chart_errors === true)
2254
status = this.library.create(this, data);
2212
- this.chart_created = true;
2213
- this.updates_since_last_creation = 0;
2255
+ else
2256
+ status = callChartLibraryCreateSafely(data);
2257
+
2258
+ if(status === false) {
2259
+ error('chart failed to be created as ' + this.library_name);
2260
}
2261
else {
2216
- try {
2217
- status = this.library.create(this, data);
2218
- this.chart_created = true;
2219
- this.updates_since_last_creation = 0;
2220
- }
2221
- catch(err) {
2222
- status = false;
2223
- error('chart failed to be created as ' + this.library_name);
2224
- }
2262
+ this.chart_created = true;
2263
+ this.updates_since_last_creation = 0;
2264
}
2226
-
2227
- if(status === false)
2228
- error('chart failed to be created as ' + this.library_name);
2265
}
2266
hideMessage();
2267
this.legendShowLatestValues();
@@ -2327,12 +2363,12 @@
2363
var ret = 0;
2364
var tolerance = 0;
2365
2330
- if(x.width === 0 || x.height === 0 || this.element.style.display === 'none') {
2366
+ if(x.width === 0 || x.height === 0) {
2367
hideChart();
2368
this.___isVisible___ = false;
2369
2370
if(this.debug === true)
2335
- this.log('isVisible: ' + this.___isVisible___);
2371
+ this.log('isVisible (width:' + x.width + ', height:' + x.height + ', display:"' + this.element.style.display + '"): ' + this.___isVisible___);
2372
2373
return this.___isVisible___;
2374
}
@@ -2485,6 +2521,9 @@
2521
2522
if(this.title === null)
2523
this.title = chart.title;
2524
+
2525
+ if(this.units === null)
2526
+ this.units = chart.units;
2527
}
2528
2529
// fetch the chart description from the netdata server
@@ -2808,7 +2847,7 @@
2847
NETDATA.options.last_page_scroll = new Date().getTime();
2848
NETDATA.options.updated_dom = false;
2849
2811
- var targets = $('div[data-netdata]').filter(':visible');
2850
+ var targets = $('div[data-netdata]'); //.filter(':visible');
2851
2852
if(NETDATA.options.debug.main_loop === true)
2853
console.log('DOM updated - there are ' + targets.length + ' charts on page.');
@@ -2854,6 +2893,11 @@
2893
}
2894
}
2895
2896
+ // bootstrap tab switching
2897
+ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
2898
+ NETDATA.onresize();
2899
+ });
2900
+
2901
NETDATA.parseDom(NETDATA.chartRefresher);
2902
}
2903
@@ -2993,7 +3037,7 @@
3037
var tooltipClassname = self.data('sparkline-tooltipclassname') || undefined;
3038
var tooltipFormat = self.data('sparkline-tooltipformat') || undefined;
3039
var tooltipPrefix = self.data('sparkline-tooltipprefix') || undefined;
2996
- var tooltipSuffix = self.data('sparkline-tooltipsuffix') || ' ' + state.chart.units;
3040
+ var tooltipSuffix = self.data('sparkline-tooltipsuffix') || ' ' + state.units;
3041
var tooltipSkipNull = self.data('sparkline-tooltipskipnull') || true;
3042
var tooltipValueLookups = self.data('sparkline-tooltipvaluelookups') || undefined;
3043
var tooltipFormatFieldlist = self.data('sparkline-tooltipformatfieldlist') || undefined;
@@ -3223,7 +3267,7 @@
3267
showLabelsOnHighlight: self.data('dygraph-showlabelsonhighlight') || true,
3268
hideOverlayOnMouseOut: self.data('dygraph-hideoverlayonmouseout') || true,
3269
3226
- ylabel: state.chart.units,
3270
+ ylabel: state.units,
3271
yLabelWidth: self.data('dygraph-ylabelwidth') || 12,
3272
3273
// the function to plot the chart
@@ -3309,10 +3353,7 @@
3353
// we are not managing the legend
3354
if(elements.hidden === null) return;
3355
3312
- if (typeof data.x === 'undefined') {
3313
- //state.legendReset();
3314
- }
3315
- else {
3356
+ if (typeof data.x !== 'undefined') {
3357
state.legendSetDate(data.x);
3358
var i = data.series.length;
3359
while(i--) {
@@ -4003,7 +4044,7 @@
4044
}
4045
},
4046
vAxis: {
4006
- title: state.chart.units,
4047
+ title: state.units,
4048
viewWindowMode: 'pretty',
4049
minValue: -0.1,
4050
maxValue: 0.1,
@@ -4105,7 +4146,7 @@
4146
state.easyPieChartEvent.timer = null;
4147
}
4148
4108
- state.easyPieChartLabel.innerHTML = '';
4149
+ state.easyPieChartLabel.innerHTML = state.legendFormatValue(null);
4150
state.easyPieChart_instance.update(0);
4151
state.easyPieChart_instance.enableAnimation();
4152
return true;
@@ -4126,8 +4167,10 @@
4167
if(max < value) max = value;
4168
4169
var pcent = 0;
4129
- if(max !== 0)
4170
+ if(max !== 0) {
4171
pcent = Math.round(value * 100 / max);
4172
+ if(pcent === 0 && value > 0) pcent = 1;
4173
+ }
4174
4175
// console.log('slot = ' + slot + ' value = ' + value + ' max = ' + max + ' pcent = ' + pcent);
4176
@@ -4156,24 +4199,29 @@
4199
};
4200
4201
NETDATA.easypiechartChartUpdate = function(state, data) {
4159
- var value = data.result[0];
4160
- if(value === null) value = 0;
4161
-
4162
- var max = (state.easyPieChartMax === null)?data.max:state.easyPieChartMax;
4163
- if(max < value) max = value;
4164
-
4165
- var pcent = 0;
4166
- if(max !== 0)
4167
- pcent = Math.round(value * 100 / max);
4202
+ var value, max, pcent;
4203
4169
- if(state.isAutoRefreshed() === true) {
4170
- state.easyPieChartLabel.innerHTML = state.legendFormatValue(value);
4171
- state.easyPieChart_instance.update(pcent);
4204
+ if(NETDATA.globalPanAndZoom.isActive() === true || state.isAutoRefreshed() === false) {
4205
+ value = null;
4206
+ max = 0;
4207
+ pcent = 0;
4208
}
4209
else {
4174
- state.easyPieChartLabel.innerHTML = '';
4175
- state.easyPieChart_instance.update(0);
4210
+ value = data.result[0];
4211
+ if(value === null) value = 0;
4212
+
4213
+ max = (state.easyPieChartMax === null)?data.max:state.easyPieChartMax;
4214
+ if(max < value) max = value;
4215
+
4216
+ pcent = 0;
4217
+ if(max !== 0) {
4218
+ pcent = Math.round(value * 100 / max);
4219
+ if(pcent === 0 && value > 0) pcent = 1;
4220
+ }
4221
}
4222
+
4223
+ state.easyPieChartLabel.innerHTML = state.legendFormatValue(value);
4224
+ state.easyPieChart_instance.update(pcent);
4225
return true;
4226
};
4227
@@ -4195,14 +4243,20 @@
4243
if(max < value) max = value;
4244
4245
var pcent = 0;
4198
- if(max !== 0)
4246
+ if(max !== 0) {
4247
pcent = Math.round(value * 100 / max);
4248
+ if(pcent === 0 && value > 0) pcent = 1;
4249
+ }
4250
4251
// console.log('value = ' + value + ' max = ' + max + ' pcent = ' + pcent);
4252
chart.data('data-percent', pcent);
4253
4254
var size = Math.min(state.chartWidth(), state.chartHeight());
4205
- var stroke = size / 15 - 2;
4255
+ if(size < 50) size = state.chartWidth();
4256
+ state.element.style.width = size + 'px';
4257
+ state.element.style.height = size + 'px';
4258
+
4259
+ var stroke = Math.floor(size / 22);
4260
if(stroke < 3) stroke = 2;
4261
4262
var valuefontsize = Math.floor((size * 2 / 3) / 5);
@@ -4228,7 +4282,7 @@
4282
var unittop = Math.round(valuetop + (valuefontsize + unitfontsize) + (size / 40));
4283
state.easyPieChartUnits = document.createElement('span');
4284
state.easyPieChartUnits.className = 'easyPieChartUnits';
4231
- state.easyPieChartUnits.innerHTML = state.chart.units;
4285
+ state.easyPieChartUnits.innerHTML = state.units;
4286
state.easyPieChartUnits.style.fontSize = unitfontsize + 'px';
4287
state.easyPieChartUnits.style.top = unittop.toString() + 'px';
4288
state.element_chart.appendChild(state.easyPieChartUnits);
@@ -4426,7 +4480,7 @@
4480
initialized: false,
4481
enabled: true,
4482
format: function(state) { return 'array'; },
4429
- options: function(state) { if(state.chart.chart_type === 'stacked') return ''; else return 'min2max'; },
4483
+ options: function(state) { return 'absolute'; },
4484
legend: function(state) { return null; },
4485
autoresize: function(state) { return false; },
4486
max_updates_to_recreate: function(state) { return 5000; },
web/index.html
+171
@@ -1007,6 +1007,177 @@ function prepareScreen(data) {
1007
+ ' role="application"></div>';
1008
});
1009
}
1010
+ else if(t.name === 'system') {
1011
+ var head = '<div style="text-align: center; vertical-align: bottom; width: 100%;">';
1012
+
1013
+ if(typeof charts['system.swap'] !== 'undefined')
1014
+ head += '<div style="margin-right: 10px;" data-netdata="system.swap"'
1015
+ + ' data-dimensions="free"'
1016
+ + ' data-append-options="percentage"'
1017
+ + ' data-chart-library="easypiechart"'
1018
+ + ' data-title="Free Swap"'
1019
+ + ' data-units="%"'
1020
+ + ' data-easypiechart-max-value="100"'
1021
+ + ' data-width="8%"'
1022
+ + ' data-height="49px"'
1023
+ + ' data-before="0"'
1024
+ + ' data-after="-' + duration.toString() + '"'
1025
+ + ' data-points="' + duration.toString() + '"'
1026
+ + ' data-colors="' + NETDATA.colors[1] + '"'
1027
+ + ' role="application"></div>';
1028
+
1029
+ if(typeof charts['system.io'] !== 'undefined') {
1030
+ head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1031
+ + ' data-dimensions="in"'
1032
+ + ' data-chart-library="easypiechart"'
1033
+ + ' data-title="Disk Read"'
1034
+ + ' data-units="KB / s"'
1035
+ + ' data-width="10%"'
1036
+ + ' data-height="49px"'
1037
+ + ' data-before="0"'
1038
+ + ' data-after="-' + duration.toString() + '"'
1039
+ + ' data-points="' + duration.toString() + '"'
1040
+ + ' data-colors="' + NETDATA.colors[0] + '"'
1041
+ + ' role="application"></div>';
1042
+
1043
+ head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1044
+ + ' data-dimensions="out"'
1045
+ + ' data-chart-library="easypiechart"'
1046
+ + ' data-title="Disk Write"'
1047
+ + ' data-units="KB / s"'
1048
+ + ' data-width="10%"'
1049
+ + ' data-height="49px"'
1050
+ + ' data-before="0"'
1051
+ + ' data-after="-' + duration.toString() + '"'
1052
+ + ' data-points="' + duration.toString() + '"'
1053
+ + ' data-colors="' + NETDATA.colors[1] + '"'
1054
+ + ' role="application"></div>';
1055
+ }
1056
+
1057
+ if(typeof charts['system.cpu'] !== 'undefined')
1058
+ head += '<div style="margin-right: 10px;" data-netdata="system.cpu"'
1059
+ + ' data-chart-library="easypiechart"'
1060
+ + ' data-title="CPU"'
1061
+ + ' data-units="%"'
1062
+ + ' data-easypiechart-max-value="100"'
1063
+ + ' data-width="11%"'
1064
+ + ' data-height="49px"'
1065
+ + ' data-after="-' + duration.toString() + '"'
1066
+ + ' data-points="' + duration.toString() + '"'
1067
+ + ' data-colors="' + NETDATA.colors[12] + '"'
1068
+ + ' role="application"></div>';
1069
+
1070
+ if(typeof charts['system.ipv4'] !== 'undefined') {
1071
+ head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1072
+ + ' data-dimensions="received"'
1073
+ + ' data-chart-library="easypiechart"'
1074
+ + ' data-title="IPv4 Inbound"'
1075
+ + ' data-units="kbps"'
1076
+ + ' data-width="10%"'
1077
+ + ' data-height="49px"'
1078
+ + ' data-before="0"'
1079
+ + ' data-after="-' + duration.toString() + '"'
1080
+ + ' data-points="' + duration.toString() + '"'
1081
+ + ' data-colors="' + NETDATA.colors[0] + '"'
1082
+ + ' role="application"></div>';
1083
+
1084
+ head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1085
+ + ' data-dimensions="sent"'
1086
+ + ' data-chart-library="easypiechart"'
1087
+ + ' data-title="IPv4 Outbound"'
1088
+ + ' data-units="kbps"'
1089
+ + ' data-width="10%"'
1090
+ + ' data-height="49px"'
1091
+ + ' data-before="0"'
1092
+ + ' data-after="-' + duration.toString() + '"'
1093
+ + ' data-points="' + duration.toString() + '"'
1094
+ + ' data-colors="' + NETDATA.colors[1] + '"'
1095
+ + ' role="application"></div>';
1096
+ }
1097
+
1098
+ if(typeof charts['system.ram'] !== 'undefined')
1099
+ head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
1100
+ + ' data-dimensions="cached|free"'
1101
+ + ' data-append-options="percentage"'
1102
+ + ' data-chart-library="easypiechart"'
1103
+ + ' data-title="Available RAM"'
1104
+ + ' data-units="%"'
1105
+ + ' data-easypiechart-max-value="100"'
1106
+ + ' data-width="8%"'
1107
+ + ' data-height="1"'
1108
+ + ' data-before="49px"'
1109
+ + ' data-after="-' + duration.toString() + '"'
1110
+ + ' data-points="' + duration.toString() + '"'
1111
+ + ' data-colors="' + NETDATA.colors[7] + '"'
1112
+ + ' role="application"></div>';
1113
+
1114
+/* if(typeof charts['system.swapio'] !== 'undefined') {
1115
+ head += "<div style=\"display: inline-block\">";
1116
+
1117
+ head += '<div style="margin-right: 10px;" data-netdata="system.swapio"'
1118
+ + ' data-dimensions="in"'
1119
+ + ' data-chart-library="easypiechart"'
1120
+ + ' data-title="Swap Read"'
1121
+ + ' data-width="100px"'
1122
+ + ' data-height="100px"'
1123
+ + ' data-before="0"'
1124
+ + ' data-after="-' + duration.toString() + '"'
1125
+ + ' data-points="' + duration.toString() + '"'
1126
+ + ' data-colors="' + NETDATA.colors[2] + '"'
1127
+ + ' role="application"></div>';
1128
+
1129
+ head += '<div style="margin-right: 10px;" data-netdata="system.swapio"'
1130
+ + ' data-dimensions="out"'
1131
+ + ' data-chart-library="easypiechart"'
1132
+ + ' data-title="Swap Write"'
1133
+ + ' data-width="100px"'
1134
+ + ' data-height="100px"'
1135
+ + ' data-before="0"'
1136
+ + ' data-after="-' + duration.toString() + '"'
1137
+ + ' data-points="' + duration.toString() + '"'
1138
+ + ' data-colors="' + NETDATA.colors[1] + '"'
1139
+ + ' role="application"></div>';
1140
+
1141
+ head += "</div>";
1142
+ }
1143
+
1144
+ if(typeof charts['system.ctxt'] !== 'undefined')
1145
+ head += '<div style="margin-right: 10px;" data-netdata="system.ctxt"'
1146
+ + ' data-chart-library="easypiechart"'
1147
+ + ' data-title="Switches"'
1148
+ + ' data-width="100px"'
1149
+ + ' data-height="100px"'
1150
+ + ' data-before="0"'
1151
+ + ' data-after="-' + duration.toString() + '"'
1152
+ + ' data-points="' + duration.toString() + '"'
1153
+ + ' data-colors="' + NETDATA.colors[3] + '"'
1154
+ + ' role="application"></div>';
1155
+
1156
+ if(typeof charts['system.intr'] !== 'undefined')
1157
+ head += '<div style="margin-right: 10px;" data-netdata="system.intr"'
1158
+ + ' data-chart-library="easypiechart"'
1159
+ + ' data-title="Interrupts"'
1160
+ + ' data-width="100px"'
1161
+ + ' data-height="100px"'
1162
+ + ' data-before="0"'
1163
+ + ' data-after="-' + duration.toString() + '"'
1164
+ + ' data-points="' + duration.toString() + '"'
1165
+ + ' data-colors="' + NETDATA.colors[7] + '"'
1166
+ + ' role="application"></div>';
1167
+*/
1168
+ head += "</div>";
1169
+ var all = '';
1170
+ $.each(t.charts, function(x, f) {
1171
+ all += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
1172
+ + ' data-width="' + pcent_width.toString() + '%"'
1173
+ + ' data-height="' + options.chartsHeight.toString() + 'px"'
1174
+ + ' data-before="0"'
1175
+ + ' data-after="-' + duration.toString() + '"'
1176
+ + ' data-id="' + name2id(options.hostname + '/' + f.id) + '"'
1177
+ + ' role="application"></div>';
1178
+ });
1179
+ html += head + all;
1180
+ }
1181
else {
1182
$.each(t.charts, function(x, f) {
1183
html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
web/netdata-swagger.yaml
+2
-2
@@ -101,7 +101,7 @@ paths:
101
description: 'The format of the data to be returned.'
102
required: true
103
type: string
104
- enum: [ 'json', 'jsonp', 'csv', 'tsv', 'tsv-excel', 'ssv', 'ssvcomma', 'datatable', 'datasource', 'html', 'array' ]
104
+ enum: [ 'json', 'jsonp', 'csv', 'tsv', 'tsv-excel', 'ssv', 'ssvcomma', 'datatable', 'datasource', 'html', 'array', 'csvjsonarray' ]
105
default: json
106
allowEmptyValue: false
107
- name: options
@@ -111,7 +111,7 @@ paths:
111
type: array
112
items:
113
type: string
114
- enum: [ 'nonzero', 'flip', 'jsonwrap', 'min2max', 'seconds', 'milliseconds', 'abs', 'absolute', 'absolute-sum', 'null2zero', 'objectrows', 'google_json' ]
114
+ enum: [ 'nonzero', 'flip', 'jsonwrap', 'min2max', 'seconds', 'milliseconds', 'abs', 'absolute', 'absolute-sum', 'null2zero', 'objectrows', 'google_json', 'percentage' ]
115
collectionFormat: pipes
116
format: ''
117
default: seconds|jsonwrap