Steve Linabery
2009-Feb-06 05:55 UTC
[Ovirt-devel] [PATCH server] Add host chart to flexchart.
Allow user to select the data function desired (min, peak, avg, rolling averages, etc.). Add scale to y-axis. Various changes to the class structure. --- src/app/controllers/graph_controller.rb | 89 +++++++- src/app/util/stats/Stats.rb | 20 ++- src/app/util/stats/StatsDataList.rb | 11 +- src/app/views/graph/history_graphs.rhtml | 2 +- src/config/routes.rb | 4 +- src/flexchart/flexchart.mxml | 33 ++- src/flexchart/org/ovirt/ApplicationBus.as | 10 +- src/flexchart/org/ovirt/DataSource.as | 60 ----- src/flexchart/org/ovirt/charts/BarChart.as | 244 ++++++++++++++------ src/flexchart/org/ovirt/charts/Chart.as | 79 +++++-- src/flexchart/org/ovirt/charts/HostChart.as | 177 ++++++++++++++ src/flexchart/org/ovirt/data/BarChartDataSource.as | 42 ++++ src/flexchart/org/ovirt/data/DataPoint.as | 16 ++- src/flexchart/org/ovirt/data/DataSeries.as | 11 +- src/flexchart/org/ovirt/data/DataSource.as | 66 ++++++ .../org/ovirt/data/FlexchartDataTransferObject.as | 90 +++++++ .../org/ovirt/data/HostChartDataSource.as | 42 ++++ src/flexchart/org/ovirt/elements/Scale.as | 87 +++++++ src/flexchart/org/ovirt/elements/SingleBar.as | 9 +- 19 files changed, 902 insertions(+), 190 deletions(-) delete mode 100644 src/flexchart/org/ovirt/DataSource.as create mode 100644 src/flexchart/org/ovirt/charts/HostChart.as create mode 100644 src/flexchart/org/ovirt/data/BarChartDataSource.as create mode 100644 src/flexchart/org/ovirt/data/DataSource.as create mode 100644 src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as create mode 100644 src/flexchart/org/ovirt/data/HostChartDataSource.as create mode 100644 src/flexchart/org/ovirt/elements/Scale.as diff --git a/src/app/controllers/graph_controller.rb b/src/app/controllers/graph_controller.rb index e8eea7e..15fa572 100644 --- a/src/app/controllers/graph_controller.rb +++ b/src/app/controllers/graph_controller.rb @@ -3,13 +3,14 @@ require 'util/stats/Stats' class GraphController < ApplicationController layout nil + def flexchart_data @id = params[:id] target = params[:target] startTime = Time.at(params[:startTime].to_i) endTime = Time.at(params[:endTime].to_i) duration = endTime.to_i - startTime.to_i - + dataFunction = DEV_KEY_FUNCTIONS[params[:dataFunction]] ? DEV_KEY_FUNCTIONS[params[:dataFunction]] : DEV_KEY_FUNCTIONS['peak'] #the maximum number of data points we want in any chart maxPoints = 100 resolution @@ -51,7 +52,7 @@ class GraphController < ApplicationController range[0].to_i, range[1].to_i - range[0].to_i, resolution, - DataFunction::Peak) + dataFunction) } } statsList = getAggregateStatsData?(requestList) @@ -62,15 +63,87 @@ class GraphController < ApplicationController data.each{ |datum| val = datum.get_value? val = 0 if (val != 0 && val.nan?) - vectors.push [datum.get_timestamp?.to_i, val] + vectors.push [datum.get_timestamp?.to_i, val, "n/a"] } graph = { :vectors => vectors, :max_value => stat.get_max_value?, - :description => target + :description => target, + :resolution => stat.get_resolution? } render :json => graph end + def host_chart_data + #expect (pool) id, resolution, startTime, target, dataFunction + @id = params[:id] + resolution = params[:resolution].to_i + startTime = Time.at(params[:startTime].to_i) + target = params[:target] + dataFunction = params[:dataFunction] + + devclass = DEV_KEY_CLASSES[target] + counter = DEV_KEY_COUNTERS[target] + + + pool = Pool.find(@id) + hosts = Host.find(:all, + :include=> :membership_audit_events, + :conditions => ['membership_audit_events.container_target_id = ?',pool]) + + requestList = [ ] + hosts.each{ |host| + + eventsInRange = host.membership_audit_events.from_pool(pool, + startTime, + Time.at(startTime.to_i + resolution)) + excluded = false + if eventsInRange.empty? + priorAuditEvent = host.membership_audit_events.most_recent_prior_event_from_pool(pool,startTime) + if priorAuditEvent.nil? || priorAuditEvent.action == MembershipAuditEvent::LEAVE + excluded = true + end + end + + if (! excluded) + requestList.push StatsRequest.new(host.hostname, + devclass, + 0, + counter, + startTime.to_i - resolution, + resolution, + resolution, + dataFunction) + end + } + + statsLists = getStatsData?(requestList) + vectors = [ ] + + myMax = 0 + statsLists.each { |statsList| + nodeName = statsList.get_node?.to_s + data = statsList.get_data? + + myVal = data[0].get_value? + myTime = data[0].get_timestamp?.to_i + if myVal.is_a?(Float) && myVal.nan? + myVal = 0 + end + myMax = [myMax, myVal].max + vectors.push [myTime, myVal, nodeName.to_s] + } + + + graph = { :vectors => vectors, + :max_value => myMax, + :description => target, + :resolution => resolution + } + + render :json => graph + end + + def get_ranges_from_event_list(list, priorEvent, startTime, endTime) results = Array.new @@ -507,6 +580,14 @@ class GraphController < ApplicationController 'load' => LoadCounter::Load_1min, 'netin' => NicCounter::Octets_rx, 'netout' => NicCounter::Octets_tx } DEV_COUNTER_KEYS = DEV_KEY_COUNTERS.invert + DEV_KEY_FUNCTIONS = { 'average' => DataFunction::Average, + 'peak' => DataFunction::Peak, + 'min' => DataFunction::Min, + 'rolling avg' => DataFunction::RollingAverage, + 'rolling peak' => DataFunction::RollingPeak, + 'rolling min' => DataFunction::RollingMin } + DEV_FUNCTION_KEYS = DEV_KEY_FUNCTIONS.invert + def _create_host_snapshot_requests(hostname, duration, resolution) requestList = [] requestList << StatsRequest.new(hostname, DEV_KEY_CLASSES['memory'], 0, DEV_KEY_COUNTERS['memory'], diff --git a/src/app/util/stats/Stats.rb b/src/app/util/stats/Stats.rb index f6b0c7a..f7e9dbe 100644 --- a/src/app/util/stats/Stats.rb +++ b/src/app/util/stats/Stats.rb @@ -27,6 +27,8 @@ require 'util/stats/StatsRequest' # This fetches a rolling average, basically average points before and after. + + def fetchRollingAve?(rrdPath, start, endTime, interval, myFunction, lIndex, returnList, aveLen=7) final = 0 my_min = 0 @@ -255,11 +257,11 @@ def fetchData?(node, devClass, instance, counter, startTime, duration, interval, sTime = startTime eTime = sTime + duration end - # Now mangle based on the intervals start = (sTime / interval).to_i * interval endTime = (eTime / interval).to_i * interval + rrdBase="/var/lib/collectd/rrd/" rrdNode=rrdBase + node + "/" @@ -309,7 +311,7 @@ def fetchData?(node, devClass, instance, counter, startTime, duration, interval, myFunction="AVERAGE" end - returnList = StatsDataList.new(node,devClass,instance, counter, localStatus, function) + returnList = StatsDataList.new(node,devClass,instance, counter, localStatus, function, interval) if ( localStatus == StatsStatus::SUCCESS ) if ( function == DataFunction::RollingPeak) || @@ -368,14 +370,23 @@ def getAggregateStatsData?(statRequestList) my_max = 0 value = 0 + resolution = 0 + node = "Aggregate" - returnList = StatsDataList.new("Aggregate",0,0, 0, 0, 0) + returnList = StatsDataList.new("Aggregate", 0, 0, 0, 0, 0, 0) statRequestList.each do |request| + #all aggregates need to have the same interval/resolution/precision + if resolution == 0 + resolution = request.get_precision? + end node = request.get_node? counter = request.get_counter? tmpList =fetchData?(request.get_node?, request.get_devClass?,request.get_instance?, request.get_counter?, \ request.get_starttime?, request.get_duration?,request.get_precision?, request.get_function?) - + #if the interval/resolution/precision varies, raise an exception + if request.get_precision? != resolution + raise + end # Now for something completely different... # The first list back will become our "master" # Each successive list will be proccesed against the master @@ -458,6 +469,7 @@ def getAggregateStatsData?(statRequestList) end returnList.set_min_value(my_min) returnList.set_max_value(my_max) + returnList.set_resolution(resolution) myList << returnList return myList diff --git a/src/app/util/stats/StatsDataList.rb b/src/app/util/stats/StatsDataList.rb index a39bcc4..6c71400 100644 --- a/src/app/util/stats/StatsDataList.rb +++ b/src/app/util/stats/StatsDataList.rb @@ -20,7 +20,7 @@ #define class StatsData List class StatsDataList - def initialize(node,devClass,instance, counter, status, function) + def initialize(node, devClass, instance, counter, status, function, resolution) # Instance variables @node = node @devClass = devClass @@ -31,6 +31,7 @@ class StatsDataList @function = function @min_value = 0 @max_value = 0 + @resolution = 0 end def get_node?() @@ -88,4 +89,12 @@ class StatsDataList def get_max_value?() return @max_value end + + def set_resolution(value) + @resolution = value + end + + def get_resolution?() + return @resolution + end end diff --git a/src/app/views/graph/history_graphs.rhtml b/src/app/views/graph/history_graphs.rhtml index 97ed67f..9488367 100644 --- a/src/app/views/graph/history_graphs.rhtml +++ b/src/app/views/graph/history_graphs.rhtml @@ -10,7 +10,7 @@ $('#flex_history_chart').flash( height: 300, wmode: 'transparent', menu: false, - flashvars: { flexchart_data: "<%= url_for :controller =>'/graph', :action => 'flexchart_data' %>/<%= @id %>/memory/<%= Time.now.to_i - 60 * 60 * 24 %>/<%= Time.now.to_i %>" } + flashvars: { flexchart_data: "<%= url_for :controller =>'/graph', :action => 'flexchart_data' %>/<%= @id %>/memory/<%= Time.now.to_i - 60 * 60 * 24 %>/<%= Time.now.to_i %>/peak" } }, { version: 9 } ); diff --git a/src/config/routes.rb b/src/config/routes.rb index 168ded5..d286c3f 100644 --- a/src/config/routes.rb +++ b/src/config/routes.rb @@ -42,8 +42,8 @@ ActionController::Routing::Routes.draw do |map| map.connect ':controller/service.wsdl', :action => 'wsdl' # Install the default route as the lowest priority. - map.connect 'graph/flexchart_data/:id/:target/:startTime/:endTime', :controller => 'graph', :action => 'flexchart_data' - map.connect 'graph/flexchart_data/:id/:target/:days', :controller => 'graph', :action => 'flexchart_data' + map.connect 'graph/flexchart_data/:id/:target/:startTime/:endTime/:dataFunction', :controller => 'graph', :action => 'flexchart_data' + map.connect 'graph/host_chart_data/:id/:target/:startTime/:resolution/:dataFunction', :controller => 'graph', :action => 'host_chart_data' map.connect ':controller/:action/:id.:format' map.connect ':controller/:action/:id' diff --git a/src/flexchart/flexchart.mxml b/src/flexchart/flexchart.mxml index c4a089f..7a86cd9 100644 --- a/src/flexchart/flexchart.mxml +++ b/src/flexchart/flexchart.mxml @@ -1,5 +1,5 @@ <?xml version="1.0"?> -<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="myInit(); populate(mainChart);" styleName="plain" horizontalScrollPolicy="off" verticalScrollPolicy="off"> +<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="myInit();" styleName="plain" horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:Script> <![CDATA[ @@ -9,10 +9,9 @@ import org.ovirt.ApplicationBus; import org.ovirt.charts.Chart; import org.ovirt.charts.BarChart; + import org.ovirt.charts.HostChart; - private function populate(container:VBox):void { - var chart:Chart = new BarChart(container, parameters['flexchart_data']); - chart.load(); + private function populate(container:Box):void { } private var expandHistory:Resize = new Resize(); @@ -23,9 +22,10 @@ private function myInit():void { + var bus:ApplicationBus = ApplicationBus.instance(); mainChart.height = Constants.height; mainChart.width = Constants.width; - hostsChart.width = Constants.width; + hostChart.width = Constants.width; expandHistory.widthTo = Constants.width; expandHistory.heightTo = Constants.height; @@ -37,26 +37,33 @@ expandResources.widthTo = Constants.width; expandResources.heightTo = Constants.height * .6666; - expandResources.target = hostsChart; + expandResources.target = hostChart; expandResources.duration = 500; contractResources.widthTo = Constants.width; contractResources.heightTo = 0; - contractResources.target = hostsChart; + contractResources.target = hostChart; contractResources.duration = 500; - ApplicationBus.instance().barClickAction = zoomIntoSeries; + bus.mainChartBarClickAction = zoomIntoSeries; + bus.closeHostChart = zoomOutSeries; + var mChart:Chart = new BarChart(mainChart, parameters['flexchart_data']); + bus.mainChart = mChart as BarChart; + mChart.load(); + + var hChart:Chart = new HostChart(hostChart); + bus.hostChart = hChart as HostChart; } private function zoomOutSeries(e:Event):void { expandHistory.end(); expandHistory.play(); contractResources.end(); contractResources.play(); - hostsChart.visible = false; + hostChart.visible = false; } private function zoomIntoSeries(e:Event):void { - hostsChart.visible=true; + hostChart.visible=true; expandResources.end(); expandResources.play(); contractHistory.end(); contractHistory.play(); } @@ -66,8 +73,8 @@ </mx:Script> - <mx:VBox id="mainChart" /> - <mx:VBox id="hostsChart" visible="false" opaqueBackground="0x00ff00" click="zoomOutSeries(event)"> - <mx:Text text="This Space Reserved for Drill-down Hosts Chart" /> + <mx:Box id="mainChart" /> + <mx:VBox id="hostChart" visible="false" opaqueBackground="0xffffff" click="zoomOutSeries(event)"> + </mx:VBox> </mx:Application> diff --git a/src/flexchart/org/ovirt/ApplicationBus.as b/src/flexchart/org/ovirt/ApplicationBus.as index 7d6d431..24474b9 100644 --- a/src/flexchart/org/ovirt/ApplicationBus.as +++ b/src/flexchart/org/ovirt/ApplicationBus.as @@ -22,6 +22,10 @@ //our ActionScript classes without needing to access Application directly package org.ovirt { + + import org.ovirt.charts.BarChart; + import org.ovirt.charts.HostChart; + public class ApplicationBus { private static var _instance:ApplicationBus; @@ -33,7 +37,11 @@ package org.ovirt { return _instance; } - public var barClickAction:Function; + public var mainChartBarClickAction:Function; + public var closeHostChart:Function; + + public var mainChart:BarChart; + public var hostChart:HostChart; } } diff --git a/src/flexchart/org/ovirt/DataSource.as b/src/flexchart/org/ovirt/DataSource.as deleted file mode 100644 index 4438900..0000000 --- a/src/flexchart/org/ovirt/DataSource.as +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright (C) 2008 Red Hat, Inc. - Written by Steve Linabery <slinabery at redhat.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301, USA. A copy of the GNU General Public License is - also available at http://www.gnu.org/copyleft/gpl.html. -*/ - -package org.ovirt { - - import com.adobe.serialization.json.JSON; - import flash.events.Event; - import flash.events.IOErrorEvent; - import flash.net.URLLoader; - import flash.net.URLRequest; - import org.ovirt.charts.Chart; - import org.ovirt.data.DataSeries; - - public class DataSource { - - private var chart:Chart; - - public function DataSource(chart:Chart) { - this.chart = chart; - } - - public function retrieveData(url:String):void { - var loader:URLLoader = new URLLoader(); - loader.addEventListener(IOErrorEvent.IO_ERROR, this.ioError); - loader.addEventListener(Event.COMPLETE, dataLoaded); - var request:URLRequest = new URLRequest(url); - loader.load(request); - } - - private function dataLoaded(event:Event):void { - var loader:URLLoader = URLLoader(event.target); - var object:Object = JSON.decode(loader.data); - var series:DataSeries = new DataSeries(object); - chart.addData(series); - } - - private function ioError( e:IOErrorEvent ):void { - trace("ioError"); - //FIXME: - //do something useful with this error - } - } -} diff --git a/src/flexchart/org/ovirt/charts/BarChart.as b/src/flexchart/org/ovirt/charts/BarChart.as index 88a75ca..08710d2 100644 --- a/src/flexchart/org/ovirt/charts/BarChart.as +++ b/src/flexchart/org/ovirt/charts/BarChart.as @@ -37,9 +37,12 @@ package org.ovirt.charts { import org.ovirt.elements.*; import org.ovirt.Constants; import org.ovirt.ApplicationBus; + import mx.core.ScrollPolicy; public class BarChart extends Chart { + private var yScale:Scale; + private var chartFrame:HBox; private var chartArea:Canvas; private var XAxisLabelArea:Canvas; private var startDateField:DateField; @@ -48,18 +51,13 @@ package org.ovirt.charts { private var endTimeField:TextInput; private var button:Button; private var menu:PopUpMenuButton; + private var functionMenu:PopUpMenuButton; private var dateBar:Box; private var datePattern:RegExp; - - public function BarChart(container:Box, - datasourceUrl:String) { - super(container,datasourceUrl); - container.setStyle("verticalGap","2"); - datePattern = /^(\d+):(\d+)$/; - } - - + /* + Private, class-specific functions + */ private function timeRangeAdjusted(event:Event):void { var t1:Number = startDateField.selectedDate.getTime() + (parseHour(startTimeField.text) * 3600 * 1000) @@ -69,14 +67,34 @@ package org.ovirt.charts { + (parseHour(endTimeField.text) * 3600 * 1000) + (parseMinute(endTimeField.text) * 60 * 1000); setEndTime(Math.floor(t2 / 1000)); + + //close the host chart when updating top chart + ApplicationBus.instance().closeHostChart.call(null,event); load(); } + + private function updateHostChart(event:MouseEvent):void { + var hostChart:HostChart = ApplicationBus.instance().hostChart; + hostChart.setId(id); + hostChart.setTarget(target); + hostChart.setStartTime((event.target as SingleBar).getStartTime() / 1000); + hostChart.setResolution((event.target as SingleBar).getResolution()); + hostChart.setDataFunction(dataFunction); + hostChart.load(); + } + private function typeSelected(event:MenuEvent):void { target = event.label; + ApplicationBus.instance().closeHostChart.call(null,event); load(); } + private function functionSelected(event:MenuEvent):void { + dataFunction = event.label; + ApplicationBus.instance().closeHostChart.call(null,event); + load(); + } private function pad(input:int):String { if (input < 10) { @@ -108,6 +126,32 @@ package org.ovirt.charts { return answer; } + + /* + Constructors + */ + public function BarChart(container:Box, + datasourceUrl:String) { + super(container,datasourceUrl); + container.setStyle("verticalGap","2"); + datePattern = /^(\d+):(\d+)$/; + } + + /* + Overriden functions + */ + override protected function initializeDataSource():void { + dataSource = new BarChartDataSource(this); + } + + override protected function setRequestAttributes(dto:FlexchartDataTransferObject):void { + dto.setId(id); + dto.setTarget(target); + dto.setStartTime(startTime); + dto.setEndTime(endTime); + dto.setDataFunction(dataFunction); + } + override public function addData(dataSeries:DataSeries):void { container.removeAllChildren(); @@ -123,11 +167,30 @@ package org.ovirt.charts { } } + + var yLabelPercentWidth:int = 8; + + chartFrame = new HBox(); + chartFrame.percentHeight = 80; + chartFrame.percentWidth = 100; + chartFrame.setVisible(true); + chartFrame.setStyle("horizontalGap","1"); + + yScale = new Scale(); + yScale.percentHeight = 100; + yScale.percentWidth = yLabelPercentWidth; + yScale.setVisible(true); + chartArea = new Canvas(); - chartArea.percentHeight = 80; - chartArea.percentWidth = 100; + chartArea.percentHeight = 100; + chartArea.percentWidth = 100 - yLabelPercentWidth; chartArea.setStyle("backgroundColor","0xbbccdd"); - this.container.addChild(chartArea); + + chartArea.verticalScrollPolicy = ScrollPolicy.OFF + + chartFrame.addChild(yScale); + chartFrame.addChild(chartArea); + this.container.addChild(chartFrame); XAxisLabelArea = new Canvas(); XAxisLabelArea.height = Constants.labelHeight; @@ -135,6 +198,9 @@ package org.ovirt.charts { XAxisLabelArea.percentWidth = 100; this.container.addChild(XAxisLabelArea); + var t1:Date = new Date(startTime * 1000); + var t2:Date = new Date(endTime * 1000); + try { dateBar = new HBox(); @@ -143,6 +209,7 @@ package org.ovirt.charts { var dataPoints:Array = dataSeries.getDataPoints(); var maxValue:Number = dataSeries.getMaxValue(); var scale:Number = maxValue; + yScale.setMax(maxValue); //avoid divide by zero if (scale == 0) { scale = 1; @@ -152,8 +219,10 @@ package org.ovirt.charts { throw new Error("No data points in range"); } + var calculatedWidth:Number = Constants.width * (chartArea.percentWidth / 100.0) ; + //the distance between left edges of adjacent bars - var gridWidth:Number = Math.floor(Constants.width / size); + var gridWidth:Number = Math.floor(calculatedWidth / size); //the width of each SingleBar (does not including padding between bars) var barWidth:Number = gridWidth - Constants.barSpacing; @@ -161,7 +230,7 @@ package org.ovirt.charts { //due to the discrete number of pixels, there may be space at the //right side of the graph that needs to be made up by padding //bars here and there - var shortfall:Number = Constants.width - (gridWidth * size); + var shortfall:Number = calculatedWidth - (gridWidth * size); var makeup:Number = Math.round(size / shortfall); var madeup:Number = 0; @@ -196,7 +265,9 @@ package org.ovirt.charts { chartArea.addChild(bar); bar.width = barWidth; bar.addEventListener(MouseEvent.CLICK, - ApplicationBus.instance().barClickAction); + ApplicationBus.instance().mainChartBarClickAction); + bar.addEventListener(MouseEvent.CLICK, + updateHostChart); bar.x = currentBarPosition; if (makeup > 0 && i % makeup == 0 && madeup < shortfall) { bar.width = bar.width + 1; @@ -214,7 +285,7 @@ package org.ovirt.charts { || i == size - 1) { var label:XAxisLabel new XAxisLabel(dateFormat.format(dataPoint.getTimestamp())); - label.setCenter(currentBarPosition + bar.width / 2); + label.setCenter(currentBarPosition + bar.width / 2 + Constants.width - calculatedWidth); label.setVisible(true); label.y = 6; XAxisLabelArea.addChild(label); @@ -235,69 +306,90 @@ package org.ovirt.charts { currentBarPosition += (bar.width + Constants.barSpacing); } - //fill in the time range selection bar - var t:Date; - var f1:Text = new Text(); - f1.text = "View data between"; - dateBar.addChild(f1); - t = new Date(dataPoints[0].getTimestamp().getTime()); - startDateField = new DateField(); - startDateField.selectedDate = t; - startDateField.editable = true; - startTimeField = new TextInput(); - startTimeField.minWidth = 50; - startTimeField.maxWidth = 50; - startTimeField.text = pad(t.hours) + ":" + pad(t.minutes); - dateBar.addChild(startTimeField); - dateBar.addChild(startDateField); - var f2:Text = new Text(); - f2.text = "and"; - dateBar.addChild(f2); - - t = new Date(dataPoints[size - 1].getTimestamp().getTime()); - endDateField = new DateField(); - endDateField.selectedDate = t; - endDateField.editable = true; - endTimeField = new TextInput(); - endTimeField.minWidth = 50; - endTimeField.maxWidth = 50; - endTimeField.text = pad(t.hours) + ":" + pad(t.minutes); - dateBar.addChild(endTimeField); - dateBar.addChild(endDateField); - - button = new Button(); - button.label = "go"; - button.addEventListener(MouseEvent.CLICK,timeRangeAdjusted); - dateBar.addChild(button); - - //FIXME: these should be fetched from the graph controller so - //that different types can be added (or restricted) dynamically - var menuItems:ArrayCollection - new ArrayCollection( [{label: "memory"}, - {label: "cpu"}, - {label: "load"}, - {label: "netin"}, - {label: "netout"}, - {label: "disk"} - ]); - - - if (menu != null) { - menu.removeEventListener(MenuEvent.ITEM_CLICK,typeSelected); - } - - menu = new PopUpMenuButton(); - menu.label = "Select Data Type"; - menu.dataProvider = menuItems; - menu.addEventListener(MenuEvent.ITEM_CLICK,typeSelected); - dateBar.addChild(menu); + t1 = new Date(dataPoints[0].getTimestamp().getTime()); + t2 = new Date(dataPoints[size - 1].getTimestamp().getTime()); } catch (e:Error) { - var err:Text = new Text(); - err.text = e.message; - err.setVisible(true); - chartArea.addChild(err); + trace(e.message); + } + + //fill in the time range selection bar + + var f1:Text = new Text(); + f1.text = "View data between"; + dateBar.addChild(f1); + + startDateField = new DateField(); + startDateField.selectedDate = t1; + startDateField.editable = true; + startTimeField = new TextInput(); + startTimeField.minWidth = 50; + startTimeField.maxWidth = 50; + startTimeField.text = pad(t1.hours) + ":" + pad(t1.minutes); + dateBar.addChild(startTimeField); + dateBar.addChild(startDateField); + var f2:Text = new Text(); + f2.text = "and"; + dateBar.addChild(f2); + + + endDateField = new DateField(); + endDateField.selectedDate = t2; + endDateField.editable = true; + endTimeField = new TextInput(); + endTimeField.minWidth = 50; + endTimeField.maxWidth = 50; + endTimeField.text = pad(t2.hours) + ":" + pad(t2.minutes); + dateBar.addChild(endTimeField); + dateBar.addChild(endDateField); + + button = new Button(); + button.label = "go"; + button.addEventListener(MouseEvent.CLICK,timeRangeAdjusted); + + dateBar.addChild(button); + + //FIXME: these should be fetched from the graph controller so + //that different types can be added (or restricted) dynamically + var menuItems:ArrayCollection + new ArrayCollection( [{label: "memory"}, + {label: "cpu"}, + {label: "load"}, + {label: "netin"}, + {label: "netout"}, + {label: "disk"} + ]); + + if (menu != null) { + menu.removeEventListener(MenuEvent.ITEM_CLICK,typeSelected); } + + menu = new PopUpMenuButton(); + menu.label = "Data Type"; + menu.dataProvider = menuItems; + menu.addEventListener(MenuEvent.ITEM_CLICK,typeSelected); + dateBar.addChild(menu); + + + var functionMenuItems:ArrayCollection + new ArrayCollection( [{label: "average"}, + {label: "peak"}, + {label: "min"}, + {label: "rolling avg"}, + {label: "rolling peak"}, + {label: "rolling min"} + ]); + + if (functionMenu != null) { + functionMenu.removeEventListener(MenuEvent.ITEM_CLICK,functionSelected); + } + + functionMenu = new PopUpMenuButton(); + functionMenu.label = "Fn Type"; + functionMenu.dataProvider = functionMenuItems; + functionMenu.addEventListener(MenuEvent.ITEM_CLICK,functionSelected); + dateBar.addChild(functionMenu); + } } } diff --git a/src/flexchart/org/ovirt/charts/Chart.as b/src/flexchart/org/ovirt/charts/Chart.as index f2faf33..ee6992e 100644 --- a/src/flexchart/org/ovirt/charts/Chart.as +++ b/src/flexchart/org/ovirt/charts/Chart.as @@ -19,58 +19,87 @@ */ package org.ovirt.charts { - import org.ovirt.DataSource; - import mx.containers.Box; - import org.ovirt.data.DataSeries; + import org.ovirt.data.DataSource; + import mx.containers.Box; + import org.ovirt.data.DataSeries; + import org.ovirt.data.FlexchartDataTransferObject; public class Chart { protected var container:Box; - protected var datasourceUrl:String; + protected var dataSource:DataSource; protected var startTime:Number; protected var endTime:Number; protected var target:String; protected var id:int; + protected var dataFunction:String; + protected var resolution:int; + /* + Inheritable functions that generally do not need overrides + */ + public function setStartTime(startTime:Number):void { + this.startTime = startTime; + } + + public function setEndTime(endTime:Number):void { + this.endTime = endTime; + } + + public function setTarget(target:String):void { + this.target = target; + } + + public function setId(id:int):void { + this.id = id; + } + + public function setDataFunction(dataFunction:String):void { + this.dataFunction = dataFunction; + } + + public function setResolution(resolution:int):void { + this.resolution = resolution; + } + + public function load():void { + var dto:FlexchartDataTransferObject = new FlexchartDataTransferObject(); + setRequestAttributes(dto); + dataSource.retrieveData(dto); + } + + /* + Constructors + */ public function Chart(container:Box, datasourceUrl:String) { this.container = container; - this.datasourceUrl = datasourceUrl; + initializeDataSource(); if (datasourceUrl != null) { var results:Array = datasourceUrl.split("/"); - if (results != null && results.length > 7) { + if (results != null && results.length > 8) { setId(new int(results[4])); setTarget(results[5] as String); setStartTime(new int(results[6])); setEndTime(new int(results[7])); + setDataFunction(results[8] as String); } } } - public function addData(dataSeries:DataSeries):void { - //override me! - } - - public function load():void { - var dataSource:DataSource = new DataSource(this); - var myString:String = "/ovirt/graph/flexchart_data/" + id + "/" + target + "/" + startTime + "/" + endTime; - dataSource.retrieveData(myString); + /* + Functions that subclasses should override + (ActionScript does not offer abstract methods) + */ + protected function initializeDataSource():void { } - public function setStartTime(startTime:Number):void { - this.startTime = startTime; + //subclasses should override this + protected function setRequestAttributes(dto:FlexchartDataTransferObject):void { } - public function setEndTime(endTime:Number):void { - this.endTime = endTime; - } - - public function setTarget(target:String):void { - this.target = target; + public function addData(dataSeries:DataSeries):void { } - public function setId(id:int):void { - this.id = id; - } } } diff --git a/src/flexchart/org/ovirt/charts/HostChart.as b/src/flexchart/org/ovirt/charts/HostChart.as new file mode 100644 index 0000000..ad46236 --- /dev/null +++ b/src/flexchart/org/ovirt/charts/HostChart.as @@ -0,0 +1,177 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + Written by Steve Linabery <slinabery at redhat.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. A copy of the GNU General Public License is + also available at http://www.gnu.org/copyleft/gpl.html. +*/ + +package org.ovirt.charts { + import flash.events.Event; + import flash.events.MouseEvent; + import mx.collections.ArrayCollection; + import mx.containers.Box; + import mx.containers.HBox; + import mx.containers.VBox; + import mx.containers.Canvas; + import mx.controls.TextInput; + import mx.controls.DateField; + import mx.controls.Button; + import mx.controls.PopUpMenuButton; + import mx.controls.Text; + import mx.events.MenuEvent; + import mx.formatters.DateFormatter; + import org.ovirt.data.*; + import org.ovirt.elements.*; + import org.ovirt.Constants; + import org.ovirt.ApplicationBus; + import mx.core.ScrollPolicy; + + public class HostChart extends Chart { + + private var yScale:Scale; + private var chartFrame:HBox; + private var chartArea:Canvas; + private var XAxisLabelArea:Canvas; + + /* + Constructors + */ + public function HostChart(container:Box) { + super(container,null); + } + + /* + Overriden functions + */ + override protected function initializeDataSource():void { + dataSource = new HostChartDataSource(this); + } + + override protected function setRequestAttributes(dto:FlexchartDataTransferObject):void { + dto.setId(id); + dto.setTarget(target); + dto.setStartTime(startTime); + dto.setResolution(resolution); + dto.setDataFunction(dataFunction); + } + + override public function addData(dataSeries:DataSeries):void { + container.removeAllChildren(); + + var i:int; + var yLabelPercentWidth:int = 8; + + chartFrame = new HBox(); + chartFrame.percentHeight = 80; + chartFrame.percentWidth = 100; + chartFrame.setVisible(true); + chartFrame.setStyle("horizontalGap","1"); + + yScale = new Scale(); + yScale.percentHeight = 100; + yScale.percentWidth = yLabelPercentWidth; + yScale.setVisible(true); + + chartArea = new Canvas(); + chartArea.percentHeight = 100; + chartArea.percentWidth = 100 - yLabelPercentWidth; + chartArea.setStyle("backgroundColor","0xbbccdd"); + + chartArea.verticalScrollPolicy = ScrollPolicy.OFF + + chartFrame.addChild(yScale); + chartFrame.addChild(chartArea); + this.container.addChild(chartFrame); + + XAxisLabelArea = new Canvas(); + XAxisLabelArea.height = Constants.labelHeight; + XAxisLabelArea.minHeight = Constants.labelHeight; + XAxisLabelArea.percentWidth = 100; + this.container.addChild(XAxisLabelArea); + + try { + var dataPoints:Array = dataSeries.getDataPoints(); + var size:int = dataPoints.length; + if (size == 0) { + throw new Error("No data points in range"); + } + + var maxValue:Number = dataSeries.getMaxValue(); + var scale:Number = maxValue; + yScale.setMax(maxValue); + //avoid divide by zero + if (scale == 0) { + scale = 1; + } + + var calculatedWidth:Number = Constants.width * (chartArea.percentWidth / 100.0) ; + + //the distance between left edges of adjacent bars + var gridWidth:Number = Math.floor(calculatedWidth / size); + + //the width of each SingleBar (does not including padding between bars) + var barWidth:Number = gridWidth - Constants.barSpacing; + + //due to the discrete number of pixels, there may be space at the + //right side of the graph that needs to be made up by padding + //bars here and there + var shortfall:Number = calculatedWidth - (gridWidth * size); + var makeup:Number = Math.round(size / shortfall); + var madeup:Number = 0; + + //variable to hold the x-coordinate of the next bar to be added to + //the chart + var currentBarPosition:int = 0; + + //add the bars & labels to the chart + var labelCounter:int = 0; + for (i = 0; i < size; i++) { + + var dataPoint:DataPoint = dataPoints[i] as DataPoint; + + var bar:SingleBar = new SingleBar(dataPoint,scale); + chartArea.addChild(bar); + bar.width = barWidth; + bar.x = currentBarPosition; + if (makeup > 0 && i % makeup == 0 && madeup < shortfall) { + bar.width = bar.width + 1; + madeup++; + } + + //if there aren't many bars, make them thinner. + if (size < 4) { + var tempWidth:Number = bar.width; + var tempX:Number = bar.x; + + bar.width = bar.width * .8; + bar.x = tempX + tempWidth * .1; + } + + + var label:XAxisLabel + new XAxisLabel(dataPoint.getNodeName()); + label.setCenter(bar.x + bar.width / 2); + label.setVisible(true); + label.y = 6; + XAxisLabelArea.addChild(label); + currentBarPosition += (bar.width + Constants.barSpacing); + } + } catch (e:Error) { + trace(e.getStackTrace()) + } + } + } +} diff --git a/src/flexchart/org/ovirt/data/BarChartDataSource.as b/src/flexchart/org/ovirt/data/BarChartDataSource.as new file mode 100644 index 0000000..69e12b1 --- /dev/null +++ b/src/flexchart/org/ovirt/data/BarChartDataSource.as @@ -0,0 +1,42 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + Written by Steve Linabery <slinabery at redhat.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. A copy of the GNU General Public License is + also available at http://www.gnu.org/copyleft/gpl.html. +*/ + +package org.ovirt.data { + + import org.ovirt.charts.Chart; + + public class BarChartDataSource extends DataSource { + + public function BarChartDataSource(chart:Chart) { + super(chart); + } + + override protected function getUrl(dto:FlexchartDataTransferObject):String { + var answer:String = "/ovirt/graph/flexchart_data/" + dto.getId() + + "/" + dto.getTarget() + + "/" + dto.getStartTime() + + "/" + dto.getEndTime() + + "/" + dto.getDataFunction(); + return answer; + } + + } + +} diff --git a/src/flexchart/org/ovirt/data/DataPoint.as b/src/flexchart/org/ovirt/data/DataPoint.as index 5d59de9..8b846e9 100644 --- a/src/flexchart/org/ovirt/data/DataPoint.as +++ b/src/flexchart/org/ovirt/data/DataPoint.as @@ -25,12 +25,17 @@ package org.ovirt.data { private var timestamp:Date; private var value:Number; private var description:String; + private var resolution:int; + private var nodeName:String; public function DataPoint (timestamp:Date, value:Number, - description:String) { + description:String, resolution:int, + nodeName:String) { this.timestamp = timestamp; this.value = value; this.description = description; + this.resolution = resolution; + this.nodeName = nodeName; } public function getTimestamp():Date { @@ -44,5 +49,14 @@ package org.ovirt.data { public function getDescription():String { return description; } + + public function getResolution():int { + return resolution; + } + + public function getNodeName():String { + return nodeName; + } + } } diff --git a/src/flexchart/org/ovirt/data/DataSeries.as b/src/flexchart/org/ovirt/data/DataSeries.as index 709ceea..21db100 100644 --- a/src/flexchart/org/ovirt/data/DataSeries.as +++ b/src/flexchart/org/ovirt/data/DataSeries.as @@ -35,6 +35,8 @@ package org.ovirt.data { this.description = object["description"] as String; dataPoints = new Array(); var inDataPoints:Array = object["vectors"] as Array; + var resolution:Number = object["resolution"] as Number; + for (var i:int = 0; i < inDataPoints.length; i++) { var value:Number = 0; var valuea:Number = (inDataPoints[i] as Array)[1] as Number; @@ -42,11 +44,17 @@ package org.ovirt.data { value = (inDataPoints[i] as Array)[1] as Number; } var seconds:Number = new Number((inDataPoints[i] as Array)[0]) * 1000; + var nodeName:String = (inDataPoints[i] as Array)[2] as String; + dataPoints.push(new DataPoint(new Date(seconds), value, - description)); + description, + resolution, + nodeName)); + } maxValue = object["max_value"] as Number; + } public function getDataPoints():Array { @@ -56,5 +64,6 @@ package org.ovirt.data { public function getMaxValue():Number { return maxValue; } + } } diff --git a/src/flexchart/org/ovirt/data/DataSource.as b/src/flexchart/org/ovirt/data/DataSource.as new file mode 100644 index 0000000..4fdd8e8 --- /dev/null +++ b/src/flexchart/org/ovirt/data/DataSource.as @@ -0,0 +1,66 @@ +/* + Copyright (C) 2008 Red Hat, Inc. + Written by Steve Linabery <slinabery at redhat.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. A copy of the GNU General Public License is + also available at http://www.gnu.org/copyleft/gpl.html. +*/ + +package org.ovirt.data { + + import com.adobe.serialization.json.JSON; + import flash.events.Event; + import flash.events.IOErrorEvent; + import flash.net.URLLoader; + import flash.net.URLRequest; + import org.ovirt.charts.Chart; + import org.ovirt.data.DataSeries; + + public class DataSource { + + private var chart:Chart; + + public function DataSource(chart:Chart) { + this.chart = chart; + } + + public function retrieveData(dto:FlexchartDataTransferObject):void { + var loader:URLLoader = new URLLoader(); + loader.addEventListener(IOErrorEvent.IO_ERROR, this.ioError); + loader.addEventListener(Event.COMPLETE, dataLoaded); + var request:URLRequest = new URLRequest(getUrl(dto)); + loader.load(request); + } + + private function dataLoaded(event:Event):void { + var loader:URLLoader = URLLoader(event.target); + var object:Object = JSON.decode(loader.data); + var series:DataSeries = new DataSeries(object); + chart.addData(series); + } + + private function ioError( e:IOErrorEvent ):void { + trace("ioError"); + //FIXME: + //do something useful with this error + } + + //subclasses should override + protected function getUrl(dto:FlexchartDataTransferObject):String { + return null; + } + + } +} diff --git a/src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as b/src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as new file mode 100644 index 0000000..8534501 --- /dev/null +++ b/src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as @@ -0,0 +1,90 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + Written by Steve Linabery <slinabery at redhat.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. A copy of the GNU General Public License is + also available at http://www.gnu.org/copyleft/gpl.html. +*/ + +package org.ovirt.data { + + public class FlexchartDataTransferObject { + + private var startTime:int; + private var endTime:int; + private var id:int; + private var target:String; + private var resolution:int; + private var averageLength:int; + private var dataFunction:String; + + public function setStartTime(startTime:int):void { + this.startTime = startTime; + } + + public function getStartTime():int { + return startTime; + } + + public function setEndTime(endTime:int):void { + this.endTime = endTime; + } + + public function getEndTime():int { + return endTime; + } + + public function setId(id:int):void { + this.id = id; + } + + public function getId():int { + return id; + } + + public function setTarget(target:String):void { + this.target = target; + } + + public function getTarget():String { + return target; + } + + public function setResolution(resolution:int):void { + this.resolution = resolution; + } + + public function getResolution():int { + return resolution; + } + + public function setAverageLength(averageLength:int):void { + this.averageLength = averageLength; + } + + public function getAverageLength():int { + return averageLength; + } + + public function setDataFunction(dataFunction:String):void { + this.dataFunction = dataFunction; + } + + public function getDataFunction():String { + return dataFunction; + } + + } +} diff --git a/src/flexchart/org/ovirt/data/HostChartDataSource.as b/src/flexchart/org/ovirt/data/HostChartDataSource.as new file mode 100644 index 0000000..7b36aec --- /dev/null +++ b/src/flexchart/org/ovirt/data/HostChartDataSource.as @@ -0,0 +1,42 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + Written by Steve Linabery <slinabery at redhat.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. A copy of the GNU General Public License is + also available at http://www.gnu.org/copyleft/gpl.html. +*/ + +package org.ovirt.data { + + import org.ovirt.charts.Chart; + + public class HostChartDataSource extends DataSource { + + public function HostChartDataSource(chart:Chart) { + super(chart); + } + + override protected function getUrl(dto:FlexchartDataTransferObject):String { + var answer:String = "/ovirt/graph/host_chart_data/" + dto.getId() + + "/" + dto.getTarget() + + "/" + dto.getStartTime() + + "/" + dto.getResolution() + + "/" + dto.getDataFunction(); + return answer; + } + + } + +} diff --git a/src/flexchart/org/ovirt/elements/Scale.as b/src/flexchart/org/ovirt/elements/Scale.as new file mode 100644 index 0000000..0238172 --- /dev/null +++ b/src/flexchart/org/ovirt/elements/Scale.as @@ -0,0 +1,87 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + Written by Steve Linabery <slinabery at redhat.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. A copy of the GNU General Public License is + also available at http://www.gnu.org/copyleft/gpl.html. +*/ + +//an object that calculates/displays tickmarks for axis scales. + +package org.ovirt.elements { + import mx.containers.Box; + import flash.events.Event; + import mx.events.FlexEvent; + import mx.events.ResizeEvent; + import mx.controls.Label; + + public class Scale extends Box { + + private var max:Number; + private var maxLabel:Label; + private var midLabel:Label; + + public function Scale() { + super(); + opaqueBackground = 0xffffff; + max = 0; + addEventListener(ResizeEvent.RESIZE,myResize); + addEventListener(FlexEvent.CREATION_COMPLETE,myResize); + addEventListener(Event.RENDER,myResize); + addEventListener(FlexEvent.INITIALIZE,myResize); + addEventListener(FlexEvent.UPDATE_COMPLETE,myResize); + + maxLabel = new Label(); + this.addChild(maxLabel); + maxLabel.setVisible(true); + + midLabel = new Label(); + this.addChild(midLabel); + midLabel.setVisible(true); + + + } + + public function setMax(max:Number):void { + this.max = max; + maxLabel.text = max.toExponential(1); + midLabel.text = (max / 2.0).toExponential(1); + } + + private function myResize(event:Event):void { + + this.height = parent.height * .90 * -1; + this.y = parent.height; + graphics.clear(); + graphics.beginFill(0x000000); + graphics.lineStyle(1); + + graphics.moveTo(width - 1,-1); + graphics.lineTo(width - 1,height); + + + graphics.moveTo(width - 4,height); + graphics.lineTo(width - 1,height); + + graphics.moveTo(width - 4,height / 2); + graphics.lineTo(width - 1,height / 2); + graphics.endFill(); + + maxLabel.y = height; + midLabel.y = height / 2; + + } + } +} diff --git a/src/flexchart/org/ovirt/elements/SingleBar.as b/src/flexchart/org/ovirt/elements/SingleBar.as index e7caf93..40ae651 100644 --- a/src/flexchart/org/ovirt/elements/SingleBar.as +++ b/src/flexchart/org/ovirt/elements/SingleBar.as @@ -63,7 +63,6 @@ package org.ovirt.elements { private function myResize(event:Event):void { - trace(event.type); this.height = (dataPoint.getValue() / scale) * parent.height * .9 * -1; this.y = parent.height; } @@ -90,5 +89,13 @@ package org.ovirt.elements { private function destroyTip(event:Event):void { ToolTipManager.destroyToolTip(tip); } + + public function getResolution():Number { + return dataPoint.getResolution(); + } + + public function getStartTime():Number { + return dataPoint.getTimestamp().getTime(); + } } } -- 1.6.0.6
Scott Seago
2009-Feb-09 14:17 UTC
[Ovirt-devel] [PATCH server] Add host chart to flexchart.
Steve Linabery wrote:> Allow user to select the data function desired (min, peak, avg, rolling averages, etc.). > Add scale to y-axis. > Various changes to the class structure. > --- > src/app/controllers/graph_controller.rb | 89 +++++++- > src/app/util/stats/Stats.rb | 20 ++- > src/app/util/stats/StatsDataList.rb | 11 +- > src/app/views/graph/history_graphs.rhtml | 2 +- > src/config/routes.rb | 4 +- > src/flexchart/flexchart.mxml | 33 ++- > src/flexchart/org/ovirt/ApplicationBus.as | 10 +- > src/flexchart/org/ovirt/DataSource.as | 60 ----- > src/flexchart/org/ovirt/charts/BarChart.as | 244 ++++++++++++++------ > src/flexchart/org/ovirt/charts/Chart.as | 79 +++++-- > src/flexchart/org/ovirt/charts/HostChart.as | 177 ++++++++++++++ > src/flexchart/org/ovirt/data/BarChartDataSource.as | 42 ++++ > src/flexchart/org/ovirt/data/DataPoint.as | 16 ++- > src/flexchart/org/ovirt/data/DataSeries.as | 11 +- > src/flexchart/org/ovirt/data/DataSource.as | 66 ++++++ > .../org/ovirt/data/FlexchartDataTransferObject.as | 90 +++++++ > .../org/ovirt/data/HostChartDataSource.as | 42 ++++ > src/flexchart/org/ovirt/elements/Scale.as | 87 +++++++ > src/flexchart/org/ovirt/elements/SingleBar.as | 9 +- > 19 files changed, 902 insertions(+), 190 deletions(-) > delete mode 100644 src/flexchart/org/ovirt/DataSource.as > create mode 100644 src/flexchart/org/ovirt/charts/HostChart.as > create mode 100644 src/flexchart/org/ovirt/data/BarChartDataSource.as > create mode 100644 src/flexchart/org/ovirt/data/DataSource.as > create mode 100644 src/flexchart/org/ovirt/data/FlexchartDataTransferObject.as > create mode 100644 src/flexchart/org/ovirt/data/HostChartDataSource.as > create mode 100644 src/flexchart/org/ovirt/elements/Scale.as >I forgot to send this out Friday night, but... ACK. Seems to work for me other than those minor issues I pointed out to you over IRC on Friday. Scott