]> arthur.barton.de Git - netdata.git/commitdiff
added API option percentage to return the percentage of each dimension against the...
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Fri, 8 Jan 2016 00:52:28 +0000 (02:52 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Fri, 8 Jan 2016 00:52:28 +0000 (02:52 +0200)
src/rrd2json.c
src/rrd2json.h
src/web_client.c
web/dashboard.css
web/dashboard.js
web/index.html
web/netdata-swagger.yaml

index 4cdc24f9f3c991ace41a4ccb1bbf8c2611d6b498..7a5f6df3e59faea26386c6a24c6f77d9c338a20e 100755 (executable)
@@ -371,6 +371,11 @@ void rrdr_disable_not_selected_dimensions(RRDR *r, const char *dims)
                for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
                        if(!strcmp(d->name, tok)) {
                                r->od[c] &= ~RRDR_HIDDEN;
+
+                               // since the user needs this dimension
+                               // make it appear as NONZERO, to return it
+                               // even if the dimension has only zeros
+                               r->od[c] |= RRDR_NONZERO;
                        }
                }
        }
@@ -425,22 +430,31 @@ void rrdr_buffer_print_format(BUFFER *wb, uint32_t format)
        }
 }
 
-uint32_t rrdr_check_options(RRDR *r, uint32_t options)
+uint32_t rrdr_check_options(RRDR *r, uint32_t options, const char *dims)
 {
        if(options & RRDR_OPTION_NONZERO) {
-               long c, i;
-               RRDDIM *rd;
-
-               // find how many dimensions are not zero
-               for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
-                       if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
-                       if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
-                       i++;
+               long i;
+
+               if(dims && *dims) {
+                       // the caller wants specific dimensions
+                       // disable NONZERO option
+                       // to make sure we don't accidentally prevent
+                       // the specific dimensions from being returned
+                       i = 0;
+               }
+               else {
+                       // find how many dimensions are not zero
+                       long c;
+                       RRDDIM *rd;
+                       for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
+                               if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
+                               if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
+                               i++;
+                       }
                }
 
-               // if with nonzero we get i = 0
-               // but c != 0, then disable nonzero
-               // to show all dimensions
+               // if with nonzero we get i = 0 (no dimensions will be returned)
+               // disable nonzero to show all dimensions
                if(!i) options &= ~RRDR_OPTION_NONZERO;
        }
 
@@ -749,6 +763,7 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
        }
 
        // for each line in the array
+       calculated_number total = 1;
        for(i = start; i != end ;i += step) {
                calculated_number *cn = &r->v[ i * r->d ];
                uint8_t *co = &r->o[ i * r->d ];
@@ -802,6 +817,20 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
                        buffer_strcat(wb, post_date);
                }
 
+               if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
+                       total = 0;
+                       for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
+                               calculated_number n = cn[c];
+
+                               if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
+                                       n = -n;
+
+                               total += n;
+                       }
+                       // prevent a division by zero
+                       if(total == 0) total = 1;
+               }
+
                // for each dimension
                for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
                        if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
@@ -820,10 +849,15 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
                                else
                                        buffer_strcat(wb, "null");
                        }
-                       else if((options & RRDR_OPTION_ABSOLUTE))
-                               buffer_rrd_value(wb, (n<0)?-n:n);
-                       else
+                       else {
+                               if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
+                                       n = -n;
+
+                               if(unlikely(options & RRDR_OPTION_PERCENTAGE))
+                                       n = n * 100 / total;
+
                                buffer_rrd_value(wb, n);
+                       }
 
                        buffer_strcat(wb, post_value);
                }
@@ -873,6 +907,7 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
        }
 
        // for each line in the array
+       calculated_number total = 1;
        for(i = start; i != end ;i += step) {
                calculated_number *cn = &r->v[ i * r->d ];
                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
                        buffer_date(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
                }
 
+               if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
+                       total = 0;
+                       for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
+                               calculated_number n = cn[c];
+
+                               if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
+                                       n = -n;
+
+                               total += n;
+                       }
+                       // prevent a division by zero
+                       if(total == 0) total = 1;
+               }
+
                // for each dimension
                for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
                        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
                                else
                                        buffer_strcat(wb, "null");
                        }
-                       else if((options & RRDR_OPTION_ABSOLUTE))
-                               buffer_rrd_value(wb, (n<0)?-n:n);
-                       else
+                       else {
+                               if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
+                                       n = -n;
+
+                               if(unlikely(options & RRDR_OPTION_PERCENTAGE))
+                                       n = n * 100 / total;
+
                                buffer_rrd_value(wb, n);
+                       }
                }
 
                buffer_strcat(wb, endline);
@@ -936,6 +990,7 @@ static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix,
        }
 
        // for each line in the array
+       calculated_number total = 1;
        for(i = start; i != end ;i += step) {
 
                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,
                calculated_number sum = 0, min = 0, max = 0, v;
                int all_null = 1, init = 1;
 
+               if(unlikely(options & RRDR_OPTION_PERCENTAGE)) {
+                       total = 0;
+                       for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
+                               calculated_number n = cn[c];
+
+                               if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
+                                       n = -n;
+
+                               total += n;
+                       }
+                       // prevent a division by zero
+                       if(total == 0) total = 1;
+               }
+
                // for each dimension
                for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
                        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,
 
                        calculated_number n = cn[c];
 
+                       if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0))
+                               n = -n;
+
+                       if(unlikely(options & RRDR_OPTION_PERCENTAGE))
+                               n = n * 100 / total;
+
                        if(unlikely(init)) {
                                if(n > 0) {
                                        min = 0;
@@ -965,7 +1040,6 @@ static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix,
 
                        if(likely(!(co[c] & RRDR_EMPTY))) {
                                all_null = 0;
-                               if((options & RRDR_OPTION_ABSOLUTE) && n < 0) n = -n;
                                sum += n;
                        }
 
@@ -1423,7 +1497,7 @@ int rrd2format(RRDSET *st, BUFFER *wb, BUFFER *dimensions, uint32_t format, long
                return 500;
        }
 
-       options = rrdr_check_options(r, options);
+       options = rrdr_check_options(r, options, (dimensions)?buffer_tostring(dimensions):NULL);
 
        if(dimensions)
                rrdr_disable_not_selected_dimensions(r, buffer_tostring(dimensions));
index 8a6ce9c02a861a9cbd274b307cf6db35da247700..d1f850d4ac073980393f9c46bc81f7c7cc7d540c 100755 (executable)
@@ -42,7 +42,7 @@ extern char *hostname;
 #define RRDR_OPTION_NONZERO            0x00000001 // don't output dimensions will just zero values
 #define RRDR_OPTION_REVERSED           0x00000002 // output the rows in reverse order (oldest to newest)
 #define RRDR_OPTION_ABSOLUTE           0x00000004 // values positive, for DATASOURCE_SSV before summing
-#define RRDR_OPTION_MIN2MAX                    0x00000008 // for DATASOURCE_SSV, out max - min
+#define RRDR_OPTION_MIN2MAX                    0x00000008 // for DATASOURCE_SSV, out max - min, instead of sum
 #define RRDR_OPTION_SECONDS                    0x00000010 // output seconds, instead of dates
 #define RRDR_OPTION_MILLISECONDS       0x00000020 // output milliseconds, instead of dates
 #define RRDR_OPTION_NULL2ZERO          0x00000040 // do not show nulls, convert them to zeros
@@ -50,6 +50,7 @@ extern char *hostname;
 #define RRDR_OPTION_GOOGLE_JSON                0x00000100 // comply with google JSON/JSONP specs
 #define RRDR_OPTION_JSON_WRAP          0x00000200 // wrap the response in a JSON header with info about the result
 #define RRDR_OPTION_LABEL_QUOTES       0x00000400 // in CSV output, wrap header labels in double quotes
+#define RRDR_OPTION_PERCENTAGE         0x00000800 // give values as percentage of total
 
 extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb);
 extern void rrd_stats_api_v1_charts(BUFFER *wb);
index 14e308f2aec5dc84104c6c0849c5f7739a123e7c..7f5e08fca8eb59d4043db05413fc4675ae924e4a 100755 (executable)
@@ -431,6 +431,8 @@ uint32_t web_client_api_request_v1_data_options(char *o)
                        ret |= RRDR_OPTION_OBJECTSROWS;
                else if(!strcmp(tok, "google_json"))
                        ret |= RRDR_OPTION_GOOGLE_JSON;
+               else if(!strcmp(tok, "percentage"))
+                       ret |= RRDR_OPTION_PERCENTAGE;
        }
 
        return ret;
index 825dc9e5c293d8433137ad37674f3cb178f907c0..98c877f7fb4e500cac8e0e6f044bf0669d27c8a5 100755 (executable)
@@ -73,7 +73,7 @@ html {
 }
 
 .netdata-message.icon {
-       color: #FAFAFA;
+       color: #F8F8F8;
        text-align: center;
        vertical-align: middle;
 }
index cadf5f93d850ad2e965bd1a7e06de5ab4aacc248..eefd2f685d3dbda7771f2c35ce1f2555428eeedd 100755 (executable)
        if(NETDATA.options.debug.main_loop === true)
                console.log('welcome to NETDATA');
 
-       window.onresize = function(event) {
-               NETDATA.options.last_page_scroll = new Date().getTime();
+       NETDATA.onresize = function() {
                NETDATA.options.last_resized = new Date().getTime();
+               NETDATA.onscroll();
        };
 
-       window.onscroll = function(event) {
+       NETDATA.onscroll = function() {
                NETDATA.options.last_page_scroll = new Date().getTime();
                if(NETDATA.options.targets === null) return;
 
                var targets = NETDATA.options.targets;
                var len = targets.length;
                while(len--) targets[len].isVisible();
-       }
+       };
+
+       window.onresize = NETDATA.onresize;
+       window.onscroll = NETDATA.onscroll;
 
        // ----------------------------------------------------------------------------------------------------------------
        // Error Handling
                this.chart = null;                                                      // object - the chart as downloaded from the server
 
                this.title = self.data('title') || null;        // the title of the chart
+               this.units = self.data('units') || null;        // the units of the chart dimensions
+               this.append_options = self.data('append-options') || null;      // the units of the chart dimensions
 
                this.validated = false;                                         // boolean - has the chart been validated?
                this.enabled = true;                                            // boolean - is the chart enabled for refresh?
                        }
                        that.element_legend_childs.series = null;
 
-                       if(that.width !== 0)
+                       if(typeof(that.width) === 'string')
                                $(that.element).css('width', that.width);
+                       else if(typeof(that.width) === 'number')
+                               $(that.element).css('width', that.width + 'px');
 
-                       if(that.height !== 0)
+                       if(typeof(that.height) === 'string')
                                $(that.element).css('height', that.height);
+                       else if(typeof(that.height) === 'number')
+                               $(that.element).css('height', that.height + 'px');
 
                        if(NETDATA.chartDefaults.min_width !== null)
                                $(that.element).css('min-width', NETDATA.chartDefaults.min_width);
 
                // hide the chart, when it is not visible - called from isVisible()
                var hideChart = function() {
-                       // no chart yet
-                       if(that.chart_created === false) return;
+                       // hide it, if it is not already hidden
+                       if(typeof that.___chartIsHidden___ !== 'undefined')
+                               return;
 
                        // we should destroy it
                        if(NETDATA.options.current.destroy_on_hide === true) {
-                               init();
-                               that.___chartIsHidden___ = undefined;
-                               return;
+                               if(that.chart_created === true) init();
                        }
-
-                       // just hide it, if it is not already hidden
-                       if(typeof that.___chartIsHidden___ === 'undefined') {
+                       else {
                                showRendering();
                                that.element_chart.style.display = 'none';
                                if(that.element_legend !== null) that.element_legend.style.display = 'none';
-                               that.___chartIsHidden___ = true;
                        }
+                       
+                       that.___chartIsHidden___ = true;
                }
 
                // unhide the chart, when it is visible - called from isVisible()
                var unhideChart = function() {
-                       if(typeof that.___chartIsHidden___ !== 'undefined') {
+                       if(typeof that.___chartIsHidden___ === 'undefined')
+                               return;
+
+                       that.___chartIsHidden___ = undefined;
+
+                       if(that.chart_created === false) {
+                               // we need to re-initialize it, to show our background
+                               // logo in bootstrap tabs, until the chart loads
+                               init();
+                       }
+                       else {
                                that.element_chart.style.display = 'inline-block';
                                if(that.element_legend !== null) that.element_legend.style.display = 'inline-block';
-                               that.___chartIsHidden___ = undefined;
                                resizeChart();
                                hideMessage();
                        }
                }
 
+               // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
+               var callChartLibraryUpdateSafely = function(data) {
+                       var status;
+
+                       try {
+                               status = that.library.update(that, data);
+                       }
+                       catch(err) {
+                               status = false;
+                       }
+
+                       return status;
+               }
+
+               // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
+               var callChartLibraryCreateSafely = function(data) {
+                       var status;
+
+                       try {
+                               status = that.library.create(that, data);
+                       }
+                       catch(err) {
+                               status = false;
+                       }
+
+                       return status;
+               }
+
                // ----------------------------------------------------------------------------------------------------------------
                // Chart Resize
 
                // a properly sized dom is available
                var resizeChart = function() {
                        if(that.isVisible() === true && that.tm.last_resized < NETDATA.options.last_resized) {
-                               that.tm.last_resized = new Date().getTime();
                                if(that.chart_created === false) return;
 
-                               if(that.needsRecreation())
+                               if(that.needsRecreation()) {
                                        init();
-
+                               }
                                else if(typeof that.library.resize === 'function') {
                                        that.library.resize(that);
 
 
                                        maxMessageFontSize();
                                }
+
+                               that.tm.last_resized = new Date().getTime();
                        }
                }
 
                                this.element_legend_childs.title_time.innerHTML = d.toLocaleTimeString();
 
                        if(this.element_legend_childs.title_units)
-                               this.element_legend_childs.title_units.innerHTML = this.chart.units;
+                               this.element_legend_childs.title_units.innerHTML = this.units;
                }
 
                this.legendShowUndefined = function() {
                        if(NETDATA.options.current.eliminate_zero_dimensions === true)
                                this.data_url += '|nonzero';
 
+                       if(this.append_options !== null)
+                               this.data_url += '|' + this.append_options.toString();
+
                        if(after)
                                this.data_url += "&after="  + after.toString();
 
                                if(this.debug === true)
                                        this.log('updating chart...');
 
-                               this.updates_since_last_creation++;
-                               if(NETDATA.options.debug.chart_errors === true) {
+                               if(NETDATA.options.debug.chart_errors === true)
                                        status = this.library.update(this, data);
+                               else
+                                       status = callChartLibraryUpdateSafely(data);
+
+                               if(status === false) {
+                                       error('chart failed to be updated as ' + this.library_name);
                                }
                                else {
-                                       try {
-                                               status = this.library.update(this, data);
-                                       }
-                                       catch(err) {
-                                               status = false;
-                                               error('chart failed to be updated as ' + this.library_name);
-                                       }
+                                       this.updates_since_last_creation++;
                                }
-
-                               if(status === false)
-                                       error('chart failed to be created as ' + this.library_name);
                        }
                        else {
                                var status = false;
                                if(this.debug === true)
                                        this.log('creating chart...');
 
-                               if(NETDATA.options.debug.chart_errors === true) {
+                               if(NETDATA.options.debug.chart_errors === true)
                                        status = this.library.create(this, data);
-                                       this.chart_created = true;
-                                       this.updates_since_last_creation = 0;
+                               else
+                                       status = callChartLibraryCreateSafely(data);
+
+                               if(status === false) {
+                                       error('chart failed to be created as ' + this.library_name);
                                }
                                else {
-                                       try {
-                                               status = this.library.create(this, data);
-                                               this.chart_created = true;
-                                               this.updates_since_last_creation = 0;
-                                       }
-                                       catch(err) {
-                                               status = false;
-                                               error('chart failed to be created as ' + this.library_name);
-                                       }
+                                       this.chart_created = true;
+                                       this.updates_since_last_creation = 0;
                                }
-
-                               if(status === false)
-                                       error('chart failed to be created as ' + this.library_name);
                        }
                        hideMessage();
                        this.legendShowLatestValues();
                        var ret = 0;
                        var tolerance = 0;
 
-                       if(x.width === 0 || x.height === 0 || this.element.style.display === 'none') {
+                       if(x.width === 0 || x.height === 0) {
                                hideChart();
                                this.___isVisible___ = false;
 
                                if(this.debug === true)
-                                       this.log('isVisible: ' + this.___isVisible___);
+                                       this.log('isVisible (width:' + x.width + ', height:' + x.height + ', display:"' + this.element.style.display + '"): ' + this.___isVisible___);
 
                                return this.___isVisible___;
                        }
 
                        if(this.title === null)
                                this.title = chart.title;
+
+                       if(this.units === null)
+                               this.units = chart.units;
                }
 
                // fetch the chart description from the netdata server
                NETDATA.options.last_page_scroll = new Date().getTime();
                NETDATA.options.updated_dom = false;
 
-               var targets = $('div[data-netdata]').filter(':visible');
+               var targets = $('div[data-netdata]'); //.filter(':visible');
 
                if(NETDATA.options.debug.main_loop === true)
                        console.log('DOM updated - there are ' + targets.length + ' charts on page.');
                        }
                }
 
+               // bootstrap tab switching
+               $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+                       NETDATA.onresize();
+               });
+               
                NETDATA.parseDom(NETDATA.chartRefresher);
        }
 
                var tooltipClassname = self.data('sparkline-tooltipclassname') || undefined;
                var tooltipFormat = self.data('sparkline-tooltipformat') || undefined;
                var tooltipPrefix = self.data('sparkline-tooltipprefix') || undefined;
-               var tooltipSuffix = self.data('sparkline-tooltipsuffix') || ' ' + state.chart.units;
+               var tooltipSuffix = self.data('sparkline-tooltipsuffix') || ' ' + state.units;
                var tooltipSkipNull = self.data('sparkline-tooltipskipnull') || true;
                var tooltipValueLookups = self.data('sparkline-tooltipvaluelookups') || undefined;
                var tooltipFormatFieldlist = self.data('sparkline-tooltipformatfieldlist') || undefined;
                        showLabelsOnHighlight: self.data('dygraph-showlabelsonhighlight') || true,
                        hideOverlayOnMouseOut: self.data('dygraph-hideoverlayonmouseout') || true,
 
-                       ylabel: state.chart.units,
+                       ylabel: state.units,
                        yLabelWidth: self.data('dygraph-ylabelwidth') || 12,
 
                        // the function to plot the chart
                                // we are not managing the legend
                                if(elements.hidden === null) return;
 
-                               if (typeof data.x === 'undefined') {
-                                       //state.legendReset();
-                               }
-                               else {
+                               if (typeof data.x !== 'undefined') {
                                        state.legendSetDate(data.x);
                                        var i = data.series.length;
                                        while(i--) {
                                }
                        },
                        vAxis: {
-                               title: state.chart.units,
+                               title: state.units,
                                viewWindowMode: 'pretty',
                                minValue: -0.1,
                                maxValue: 0.1,
                        state.easyPieChartEvent.timer = null;
                }
 
-               state.easyPieChartLabel.innerHTML = '';
+               state.easyPieChartLabel.innerHTML = state.legendFormatValue(null);
                state.easyPieChart_instance.update(0);
                state.easyPieChart_instance.enableAnimation();
                return true;
                if(max < value) max = value;
                
                var pcent = 0;
-               if(max !== 0)
+               if(max !== 0) {
                        pcent = Math.round(value * 100 / max);
+                       if(pcent === 0 && value > 0) pcent = 1;
+               }
 
                // console.log('slot = ' + slot + ' value = ' + value + ' max = ' + max + ' pcent = ' + pcent);
 
        };
 
        NETDATA.easypiechartChartUpdate = function(state, data) {
-               var value = data.result[0];
-               if(value === null) value = 0;
-
-               var max = (state.easyPieChartMax === null)?data.max:state.easyPieChartMax;
-               if(max < value) max = value;
-
-               var pcent = 0;
-               if(max !== 0)
-                       pcent = Math.round(value * 100 / max);
+               var value, max, pcent;
 
-               if(state.isAutoRefreshed() === true) {
-                       state.easyPieChartLabel.innerHTML = state.legendFormatValue(value);
-                       state.easyPieChart_instance.update(pcent);
+               if(NETDATA.globalPanAndZoom.isActive() === true || state.isAutoRefreshed() === false) {
+                       value = null;
+                       max = 0;
+                       pcent = 0;
                }
                else {
-                       state.easyPieChartLabel.innerHTML = '';
-                       state.easyPieChart_instance.update(0);
+                       value = data.result[0];
+                       if(value === null) value = 0;
+
+                       max = (state.easyPieChartMax === null)?data.max:state.easyPieChartMax;
+                       if(max < value) max = value;
+
+                       pcent = 0;
+                       if(max !== 0) {
+                               pcent = Math.round(value * 100 / max);
+                               if(pcent === 0 && value > 0) pcent = 1;
+                       }
                }
+
+               state.easyPieChartLabel.innerHTML = state.legendFormatValue(value);
+               state.easyPieChart_instance.update(pcent);
                return true;
        };
 
                if(max < value) max = value;
 
                var pcent = 0;
-               if(max !== 0)
+               if(max !== 0) {
                        pcent = Math.round(value * 100 / max);
+                       if(pcent === 0 && value > 0) pcent = 1;
+               }
 
                // console.log('value = ' + value + ' max = ' + max + ' pcent = ' + pcent);
                chart.data('data-percent', pcent);
 
                var size = Math.min(state.chartWidth(), state.chartHeight());
-               var stroke = size / 15 - 2;
+               if(size < 50) size = state.chartWidth();
+               state.element.style.width = size + 'px';
+               state.element.style.height = size + 'px';
+
+               var stroke = Math.floor(size / 22);
                if(stroke < 3) stroke = 2;
 
                var valuefontsize = Math.floor((size * 2 / 3) / 5);
                var unittop = Math.round(valuetop + (valuefontsize + unitfontsize) + (size / 40));
                state.easyPieChartUnits = document.createElement('span');
                state.easyPieChartUnits.className = 'easyPieChartUnits';
-               state.easyPieChartUnits.innerHTML = state.chart.units;
+               state.easyPieChartUnits.innerHTML = state.units;
                state.easyPieChartUnits.style.fontSize = unitfontsize + 'px';
                state.easyPieChartUnits.style.top = unittop.toString() + 'px';
                state.element_chart.appendChild(state.easyPieChartUnits);
                        initialized: false,
                        enabled: true,
                        format: function(state) { return 'array'; },
-                       options: function(state) { if(state.chart.chart_type === 'stacked') return ''; else return 'min2max'; },
+                       options: function(state) { return 'absolute'; },
                        legend: function(state) { return null; },
                        autoresize: function(state) { return false; },
                        max_updates_to_recreate: function(state) { return 5000; },
index 778972513aa96ad6a4f872f6ec518a59fc262cc0..a8d54531d73712858e1dd0714951e8f7fac92386 100755 (executable)
@@ -1007,6 +1007,177 @@ function prepareScreen(data) {
                                        + ' role="application"></div>';
                        });
                }
+               else if(t.name === 'system') {
+                       var head = '<div style="text-align: center; vertical-align: bottom; width: 100%;">';
+
+                       if(typeof charts['system.swap'] !== 'undefined')
+                               head += '<div style="margin-right: 10px;" data-netdata="system.swap"'
+                               + ' data-dimensions="free"'
+                               + ' data-append-options="percentage"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="Free Swap"'
+                               + ' data-units="%"'
+                               + ' data-easypiechart-max-value="100"'
+                               + ' data-width="8%"'
+                               + ' data-height="49px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[1] + '"'
+                               + ' role="application"></div>';
+
+                       if(typeof charts['system.io'] !== 'undefined') {
+                               head += '<div style="margin-right: 10px;" data-netdata="system.io"'
+                               + ' data-dimensions="in"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="Disk Read"'
+                               + ' data-units="KB / s"'
+                               + ' data-width="10%"'
+                               + ' data-height="49px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[0] + '"'
+                               + ' role="application"></div>';
+
+                               head += '<div style="margin-right: 10px;" data-netdata="system.io"'
+                               + ' data-dimensions="out"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="Disk Write"'
+                               + ' data-units="KB / s"'
+                               + ' data-width="10%"'
+                               + ' data-height="49px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[1] + '"'
+                               + ' role="application"></div>';
+                       }
+
+                       if(typeof charts['system.cpu'] !== 'undefined')
+                               head += '<div style="margin-right: 10px;" data-netdata="system.cpu"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="CPU"'
+                               + ' data-units="%"'
+                               + ' data-easypiechart-max-value="100"'
+                               + ' data-width="11%"'
+                               + ' data-height="49px"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[12] + '"'
+                               + ' role="application"></div>';
+
+                       if(typeof charts['system.ipv4'] !== 'undefined') {
+                               head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
+                               + ' data-dimensions="received"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="IPv4 Inbound"'
+                               + ' data-units="kbps"'
+                               + ' data-width="10%"'
+                               + ' data-height="49px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[0] + '"'
+                               + ' role="application"></div>';
+
+                               head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
+                               + ' data-dimensions="sent"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="IPv4 Outbound"'
+                               + ' data-units="kbps"'
+                               + ' data-width="10%"'
+                               + ' data-height="49px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[1] + '"'
+                               + ' role="application"></div>';
+                       }
+
+                       if(typeof charts['system.ram'] !== 'undefined')
+                               head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
+                               + ' data-dimensions="cached|free"'
+                               + ' data-append-options="percentage"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="Available RAM"'
+                               + ' data-units="%"'
+                               + ' data-easypiechart-max-value="100"'
+                               + ' data-width="8%"'
+                               + ' data-height="1"'
+                               + ' data-before="49px"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[7] + '"'
+                               + ' role="application"></div>';
+
+/*                     if(typeof charts['system.swapio'] !== 'undefined') {
+                               head += "<div style=\"display: inline-block\">";
+
+                               head += '<div style="margin-right: 10px;" data-netdata="system.swapio"'
+                               + ' data-dimensions="in"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="Swap Read"'
+                               + ' data-width="100px"'
+                               + ' data-height="100px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[2] + '"'
+                               + ' role="application"></div>';
+
+                               head += '<div style="margin-right: 10px;" data-netdata="system.swapio"'
+                               + ' data-dimensions="out"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="Swap Write"'
+                               + ' data-width="100px"'
+                               + ' data-height="100px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[1] + '"'
+                               + ' role="application"></div>';
+
+                               head += "</div>";
+                       }
+
+                       if(typeof charts['system.ctxt'] !== 'undefined')
+                               head += '<div style="margin-right: 10px;" data-netdata="system.ctxt"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="Switches"'
+                               + ' data-width="100px"'
+                               + ' data-height="100px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[3] + '"'
+                               + ' role="application"></div>';
+
+                       if(typeof charts['system.intr'] !== 'undefined')
+                               head += '<div style="margin-right: 10px;" data-netdata="system.intr"'
+                               + ' data-chart-library="easypiechart"'
+                               + ' data-title="Interrupts"'
+                               + ' data-width="100px"'
+                               + ' data-height="100px"'
+                               + ' data-before="0"'
+                               + ' data-after="-' + duration.toString() + '"'
+                               + ' data-points="' + duration.toString() + '"'
+                               + ' data-colors="' + NETDATA.colors[7] + '"'
+                               + ' role="application"></div>';
+*/
+                       head += "</div>";
+                       var all = '';
+                       $.each(t.charts, function(x, f) {
+                               all += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
+                                       + ' data-width="' + pcent_width.toString() + '%"'
+                                       + ' data-height="' + options.chartsHeight.toString() + 'px"'
+                                       + ' data-before="0"'
+                                       + ' data-after="-' + duration.toString() + '"'
+                                       + ' data-id="' + name2id(options.hostname + '/' + f.id) + '"'
+                                       + ' role="application"></div>';
+                       });
+                       html += head + all;
+               }
                else {
                        $.each(t.charts, function(x, f) {
                                html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
index 7d7bc656074270c5ce5a64ffa4b1b9d5b6d81f3e..bb1a0bcb41124d7ada2de00db3a9e0fa80dc2b62 100755 (executable)
@@ -101,7 +101,7 @@ paths:
           description: 'The format of the data to be returned.'
           required: true
           type: string
-          enum: [ 'json', 'jsonp', 'csv', 'tsv', 'tsv-excel', 'ssv', 'ssvcomma', 'datatable', 'datasource', 'html', 'array' ]
+          enum: [ 'json', 'jsonp', 'csv', 'tsv', 'tsv-excel', 'ssv', 'ssvcomma', 'datatable', 'datasource', 'html', 'array', 'csvjsonarray' ]
           default: json
           allowEmptyValue: false
         - name: options
@@ -111,7 +111,7 @@ paths:
           type: array
           items:
             type: string
-            enum: [ 'nonzero', 'flip', 'jsonwrap', 'min2max', 'seconds', 'milliseconds', 'abs', 'absolute', 'absolute-sum', 'null2zero', 'objectrows', 'google_json' ]
+            enum: [ 'nonzero', 'flip', 'jsonwrap', 'min2max', 'seconds', 'milliseconds', 'abs', 'absolute', 'absolute-sum', 'null2zero', 'objectrows', 'google_json', 'percentage' ]
             collectionFormat: pipes
             format: ''
           default: seconds|jsonwrap