modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java | 442 +++++----- modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java | 286 +----- 2 files changed, 285 insertions(+), 443 deletions(-)
New commits: commit ab5629677b79df0286df8ced99e919264e0b6aba Author: Jirka Kremser jkremser@redhat.com Date: Thu Nov 21 12:31:24 2013 +0200
[BZ 1038067] - Resource Summary/Activity shows summary of disabled metrics - fixing the issue for resource groups (Autogroups and compatible ones).
Also doing some refactoring, because the same code was in the portlet for resource and for group, so I moved the common functionality to the group portled and resource portlet overrides the different parts. What would be even better is to introduce a common abstract class in the new package org.rhq.coregui.client.dashboard.portlets.common (the same way it is done in the org.rhq.coregui.client.inventory.common package). However, all the portlets follow this pattern (ResourcePortlet extends GroupPortles), so it would be inconsistent.
After the refactoring, the code is more flat because the callback hell is not so evil when using own methods for each callback. The toll for it is the number of arguments that has to be passed to those methods representing the state that is needed inside the method.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java index c1d7269..e9ee86c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java @@ -20,9 +20,9 @@ package org.rhq.coregui.client.dashboard.portlets.groups;
import java.util.ArrayList; import java.util.Arrays; -import java.util.EnumSet; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set;
import com.google.gwt.user.client.Timer; @@ -49,14 +49,15 @@ import com.smartgwt.client.widgets.layout.VLayout; import org.rhq.core.domain.common.EntityContext; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertySimple; +import org.rhq.core.domain.criteria.MeasurementScheduleCriteria; import org.rhq.core.domain.criteria.ResourceGroupCriteria; import org.rhq.core.domain.dashboard.DashboardPortlet; import org.rhq.core.domain.measurement.MeasurementDefinition; +import org.rhq.core.domain.measurement.MeasurementSchedule; import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite; -import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.group.GroupCategory; -import org.rhq.core.domain.resource.group.ResourceGroup; import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite; +import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.coregui.client.LinkManager; import org.rhq.coregui.client.components.measurement.CustomConfigMeasurementRangeEditor; @@ -73,9 +74,10 @@ import org.rhq.coregui.client.inventory.common.detail.summary.AbstractActivityVi import org.rhq.coregui.client.inventory.common.graph.CustomDateRangeState; import org.rhq.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView; import org.rhq.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3MultiLineGraph; -import org.rhq.coregui.client.inventory.resource.type.ResourceTypeRepository; import org.rhq.coregui.client.util.BrowserUtility; import org.rhq.coregui.client.util.Log; +import org.rhq.coregui.client.util.async.Command; +import org.rhq.coregui.client.util.async.CountDownLatch; import org.rhq.coregui.client.util.enhanced.EnhancedVLayout;
/** @@ -101,6 +103,9 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin //instance ui widgets
protected Timer refreshTimer; + + private volatile List<MeasurementSchedule> enabledSchedules = null; + private volatile boolean renderChart = false;
// final version needed to pass to anon classes // so we can call refresh in anon callback handler @@ -221,10 +226,80 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin */ protected void getRecentMetrics() {
+ renderChart = true; + //display container final VLayout column = new VLayout(); column.setHeight(10);//pack
+ final CountDownLatch latch = CountDownLatch.create(2, new Command() { + @Override + public void execute() { + if (enabledSchedules.isEmpty() || !renderChart) { + DynamicForm row = getEmptyDataForm(); + column.addMember(row); + return; + } + //build id mapping for measurementDefinition instances Ex. Free Memory -> MeasurementDefinition[100071] + final HashMap<String, MeasurementDefinition> measurementDefMap = new HashMap<String, MeasurementDefinition>(); + for (MeasurementSchedule schedule : enabledSchedules) { + measurementDefMap.put(schedule.getDefinition().getDisplayName(), schedule.getDefinition()); + } + Set<String> displayNamesSet = measurementDefMap.keySet(); + //bundle definition ids for async call. + int[] definitionArrayIds = new int[displayNamesSet.size()]; + final String[] displayOrder = new String[displayNamesSet.size()]; + displayNamesSet.toArray(displayOrder); + //sort the charting data ex. Free Memory, Free Swap Space,..System Load + Arrays.sort(displayOrder); + + //organize definitionArrayIds for ordered request on server. + int index = 0; + for (String definitionToDisplay : displayOrder) { + definitionArrayIds[index++] = measurementDefMap.get(definitionToDisplay) + .getId(); + } + + fetchEnabledMetrics(enabledSchedules, definitionArrayIds, displayOrder, measurementDefMap, column); + } + }); + + //fetch only enabled schedules + fetchEnabledSchedules(latch); + + //fetch the resource type + fetchResourceType(latch, column); + + //cleanup + for (Canvas child : recentMeasurementsContent.getChildren()) { + child.destroy(); + } + recentMeasurementsContent.addChild(column); + recentMeasurementsContent.markForRedraw(); + } + + private void fetchEnabledSchedules(final CountDownLatch latch) { + MeasurementScheduleCriteria criteria = new MeasurementScheduleCriteria(); + criteria.addFilterEnabled(true); + criteria.fetchDefinition(true); + criteria.setPageControl(PageControl.getUnlimitedInstance()); + addFilterKey(criteria); + GWTServiceLookup.getMeasurementDataService().findMeasurementSchedulesByCriteria(criteria, new AsyncCallback<PageList<MeasurementSchedule>>() { + + @Override + public void onSuccess(PageList<MeasurementSchedule> result) { + enabledSchedules = result; + latch.countDown(); + } + + @Override + public void onFailure(Throwable caught) { + latch.countDown(); + } + }); + } + + protected void fetchResourceType(final CountDownLatch latch, final VLayout layout) { //locate resourceGroupRef ResourceGroupCriteria criteria = new ResourceGroupCriteria(); criteria.addFilterId(this.groupId); @@ -251,211 +326,18 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin Log.debug("Error retrieving resource group composite for group [" + groupId + "]:" + caught.getMessage()); setRefreshing(false); + latch.countDown(); }
@Override public void onSuccess(PageList<ResourceGroupComposite> results) { - if (!results.isEmpty()) { - final ResourceGroupComposite groupComposite = results.get(0); - final ResourceGroup group = groupComposite.getResourceGroup(); - if (group.getGroupCategory() == GroupCategory.COMPATIBLE) { - // Load the fully fetched ResourceType. - ResourceType groupType = group.getResourceType(); - ResourceTypeRepository.Cache.getInstance().getResourceTypes( - groupType.getId(), - EnumSet.of(ResourceTypeRepository.MetadataType.content, - ResourceTypeRepository.MetadataType.operations, - ResourceTypeRepository.MetadataType.measurements, - ResourceTypeRepository.MetadataType.events, - ResourceTypeRepository.MetadataType.resourceConfigurationDefinition), - new ResourceTypeRepository.TypeLoadedCallback() { - public void onTypesLoaded(ResourceType type) { - group.setResourceType(type); - //metric definitions - Set<MeasurementDefinition> definitions = type.getMetricDefinitions(); - - //build id mapping for measurementDefinition instances Ex. Free Memory -> MeasurementDefinition[100071] - final HashMap<String, MeasurementDefinition> measurementDefMap = new HashMap<String, MeasurementDefinition>(); - for (MeasurementDefinition definition : definitions) { - measurementDefMap.put(definition.getDisplayName(), definition); - } - //bundle definition ids for asynch call. - int[] definitionArrayIds = new int[definitions.size()]; - final String[] displayOrder = new String[definitions.size()]; - measurementDefMap.keySet().toArray(displayOrder); - //sort the charting data ex. Free Memory, Free Swap Space,..System Load - Arrays.sort(displayOrder); - - //organize definitionArrayIds for ordered request on server. - int index = 0; - for (String definitionToDisplay : displayOrder) { - definitionArrayIds[index++] = measurementDefMap.get(definitionToDisplay) - .getId(); - } - - GWTServiceLookup.getMeasurementDataService().findDataForCompatibleGroup( - groupId, definitionArrayIds, - CustomDateRangeState.getInstance().getStartTime(), - CustomDateRangeState.getInstance().getEndTime(), 60, - new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() { - @Override - public void onFailure(Throwable caught) { - Log.debug("Error retrieving recent metrics charting data for group [" - + groupId + "]:" + caught.getMessage()); - setRefreshing(false); - } - - @Override - public void onSuccess( - List<List<MeasurementDataNumericHighLowComposite>> results) { - if (!results.isEmpty()) { - boolean someChartedData = false; - //iterate over the retrieved charting data - for (int index = 0; index < displayOrder.length; index++) { - //retrieve the correct measurement definition - final MeasurementDefinition md = measurementDefMap - .get(displayOrder[index]); - - //load the data results for the given metric definition - List<MeasurementDataNumericHighLowComposite> data = results - .get(index); - - //locate last and minimum values. - double lastValue = -1; - double minValue = Double.MAX_VALUE;// - for (MeasurementDataNumericHighLowComposite d : data) { - if ((!Double.isNaN(d.getValue())) - && (!String.valueOf(d.getValue()).contains("NaN"))) { - if (d.getValue() < minValue) { - minValue = d.getValue(); - } - lastValue = d.getValue(); - } - } - - //collapse the data into comma delimited list for consumption by third party javascript library(jquery.sparkline) - String commaDelimitedList = ""; - - for (MeasurementDataNumericHighLowComposite d : data) { - if ((!Double.isNaN(d.getValue())) - && (!String.valueOf(d.getValue()).contains("NaN"))) { - commaDelimitedList += d.getValue() + ","; - } - } - DynamicForm row = new DynamicForm(); - row.setNumCols(3); - row.setColWidths(65, "*", 100); - row.setWidth100(); - row.setAutoHeight(); - row.setOverflow(Overflow.VISIBLE); - HTMLFlow graph = new HTMLFlow(); - // String contents = "<span id='sparkline_" + index + "' class='dynamicsparkline' width='0'>" - // + commaDelimitedList + "</span>"; - String contents = "<span id='sparkline_" + index - + "' class='dynamicsparkline' width='0' " + "values='" - + commaDelimitedList + "'>...</span>"; - graph.setContents(contents); - graph.setContentsType(ContentsType.PAGE); - //disable scrollbars on span - graph.setScrollbarSize(0); - - CanvasItem graphContainer = new CanvasItem(); - graphContainer.setShowTitle(false); - graphContainer.setHeight(16); - graphContainer.setWidth(60); - graphContainer.setCanvas(graph); - - final String title = md.getDisplayName(); - LinkItem link = AbstractActivityView.newLinkItem(title, - null); - link.setTooltip(title); - link.setTitleVAlign(VerticalAlignment.TOP); - link.setAlign(Alignment.LEFT); - link.setClipValue(true); - link.setWrap(true); - link.setHeight(26); - if (!BrowserUtility.isBrowserPreIE9()) { - - link.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - ChartViewWindow window = new ChartViewWindow( - title, "", refreshablePortlet); - CompositeGroupD3GraphListView graph = new CompositeGroupD3MultiLineGraph( - groupId, md.getId(), isAutoGroup); - window.addItem(graph); - graph.populateData(); - window.show(); - } - }); - } else { - link.disable(); - } - - //Value - String convertedValue = AbstractActivityView - .convertLastValueForDisplay(lastValue, md); - StaticTextItem value = AbstractActivityView - .newTextItem(convertedValue); - value.setVAlign(VerticalAlignment.TOP); - value.setAlign(Alignment.RIGHT); - value.setWidth("100%"); - - row.setItems(graphContainer, link, value); - row.setWidth100(); - //if graph content returned - if ((!md.getName().trim().contains("Trait.")) - && (lastValue != -1)) { - column.addMember(row); - someChartedData = true; - } - } - if (!someChartedData) {// when there are results but no chartable entries. - DynamicForm row = AbstractActivityView - .createEmptyDisplayRow(AbstractActivityView.RECENT_MEASUREMENTS_GROUP_NONE); - column.addMember(row); - } else { - //insert see more link - DynamicForm row = new DynamicForm(); - String link = LinkManager - .getGroupMonitoringGraphsLink(context); - AbstractActivityView.addSeeMoreLink(row, link, column); - } - //call out to 3rd party javascript lib - new Timer() { - @Override - public void run() { - BrowserUtility.graphSparkLines(); - } - }.schedule(200); - - } else { - DynamicForm row = AbstractActivityView.createEmptyDisplayRow( - AbstractActivityView.RECENT_MEASUREMENTS_GROUP_NONE); - column.addMember(row); - } - setRefreshing(false); - } - } - ); - } - }); - } - } else { - DynamicForm row = AbstractActivityView - .createEmptyDisplayRow(AbstractActivityView.RECENT_MEASUREMENTS_GROUP_NONE); - column.addMember(row); - setRefreshing(false); + if (results.isEmpty() + || results.get(0).getResourceGroup().getGroupCategory() != GroupCategory.COMPATIBLE) { + renderChart = false; } + latch.countDown(); } }); - - //cleanup - for (Canvas child : recentMeasurementsContent.getChildren()) { - child.destroy(); - } - recentMeasurementsContent.addChild(column); - recentMeasurementsContent.markForRedraw(); }
@Override @@ -497,10 +379,10 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin protected void setRefreshing(boolean currentlyRefreshing) { this.currentlyLoading = currentlyRefreshing; } - public static class ChartViewWindow extends Window {
+ public static class ChartViewWindow extends Window {
- public ChartViewWindow(String title, String windowTitle,final GroupMetricsPortlet portlet) { + public ChartViewWindow(String title, String windowTitle, final GroupMetricsPortlet portlet) { super(); if ((windowTitle != null) && (!windowTitle.trim().isEmpty())) { setTitle(windowTitle + ": " + title); @@ -533,4 +415,156 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin
} } + + protected void fetchEnabledMetrics(List<MeasurementSchedule> schedules, int[] definitionArrayIds, + final String[] displayOrder, final Map<String, MeasurementDefinition> measurementDefMap, final VLayout layout) { + GWTServiceLookup.getMeasurementDataService().findDataForCompatibleGroup(groupId, definitionArrayIds, + CustomDateRangeState.getInstance().getStartTime(), CustomDateRangeState.getInstance().getEndTime(), 60, + new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() { + @Override + public void onFailure(Throwable caught) { + Log.debug("Error retrieving recent metrics charting data for group [" + groupId + "]:" + + caught.getMessage()); + setRefreshing(false); + } + + @Override + public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> results) { + renderData(results, displayOrder, measurementDefMap, layout); + } + }); + } + + + protected void renderData(List<List<MeasurementDataNumericHighLowComposite>> results, String[] displayOrder, Map<String, MeasurementDefinition> measurementDefMap, VLayout layout) { + if (!results.isEmpty() && !measurementDefMap.isEmpty()) { + boolean someChartedData = false; + //iterate over the retrieved charting data + for (int index = 0; index < displayOrder.length; index++) { + //retrieve the correct measurement definition + final MeasurementDefinition md = measurementDefMap + .get(displayOrder[index]); + + //load the data results for the given metric definition + List<MeasurementDataNumericHighLowComposite> data = results + .get(index); + + //locate last and minimum values. + double lastValue = -1; + double minValue = Double.MAX_VALUE; + //collapse the data into comma delimited list for consumption by third party javascript library(jquery.sparkline) + String commaDelimitedList = ""; + for (MeasurementDataNumericHighLowComposite d : data) { + if ((!Double.isNaN(d.getValue())) + && (!String.valueOf(d.getValue()).contains("NaN"))) { + commaDelimitedList += d.getValue() + ","; + if (d.getValue() < minValue) { + minValue = d.getValue(); + } + lastValue = d.getValue(); + } + } + DynamicForm row = new DynamicForm(); + row.setNumCols(3); + row.setColWidths(65, "*", 100); + row.setWidth100(); + row.setAutoHeight(); + row.setOverflow(Overflow.VISIBLE); + HTMLFlow graph = new HTMLFlow(); + String contents = "<span id='sparkline_" + index + + "' class='dynamicsparkline' width='0' " + "values='" + + commaDelimitedList + "'>...</span>"; + graph.setContents(contents); + graph.setContentsType(ContentsType.PAGE); + //disable scrollbars on span + graph.setScrollbarSize(0); + + CanvasItem graphContainer = new CanvasItem(); + graphContainer.setShowTitle(false); + graphContainer.setHeight(16); + graphContainer.setWidth(60); + graphContainer.setCanvas(graph); + + final String title = md.getDisplayName(); + LinkItem link = AbstractActivityView.newLinkItem(title, + null); + link.setTooltip(title); + link.setTitleVAlign(VerticalAlignment.TOP); + link.setAlign(Alignment.LEFT); + link.setClipValue(true); + link.setWrap(true); + link.setHeight(26); + if (!BrowserUtility.isBrowserPreIE9()) { + + link.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + showPopupWithChart(title, md); + } + }); + } else { + link.disable(); + } + + //Value + String convertedValue = AbstractActivityView + .convertLastValueForDisplay(lastValue, md); + StaticTextItem value = AbstractActivityView + .newTextItem(convertedValue); + value.setVAlign(VerticalAlignment.TOP); + value.setWidth("100%"); + + row.setItems(graphContainer, link, value); + row.setWidth100(); + //if graph content returned + if ((!md.getName().trim().contains("Trait.")) + && (lastValue != -1)) { + layout.addMember(row); + someChartedData = true; + } + } + if (!someChartedData) {// when there are results but no chartable entries. + DynamicForm row = getEmptyDataForm(); + layout.addMember(row); + } else { + //insert see more link + DynamicForm row = new DynamicForm(); + String link = getSeeMoreLink(); + AbstractActivityView.addSeeMoreLink(row, link, layout); + } + //call out to 3rd party javascript lib + new Timer() { + @Override + public void run() { + BrowserUtility.graphSparkLines(); + } + }.schedule(200); + + } else { + DynamicForm row = getEmptyDataForm(); + layout.addMember(row); + } + setRefreshing(false); + } + + protected void showPopupWithChart(final String title, final MeasurementDefinition md) { + ChartViewWindow window = new ChartViewWindow(title, "", refreshablePortlet); + CompositeGroupD3GraphListView graph = new CompositeGroupD3MultiLineGraph(groupId, md.getId(), isAutoGroup()); + window.addItem(graph); + graph.populateData(); + window.show(); + } + + protected DynamicForm getEmptyDataForm() { + return AbstractActivityView.createEmptyDisplayRow(AbstractActivityView.RECENT_MEASUREMENTS_GROUP_NONE); + } + + protected String getSeeMoreLink() { + return LinkManager.getGroupMonitoringGraphsLink(context); + } + + protected MeasurementScheduleCriteria addFilterKey(MeasurementScheduleCriteria criteria) { + criteria.addFilterResourceGroupId(groupId); + return criteria; + } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java index df4e659..93d2d7c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java @@ -18,27 +18,12 @@ */ package org.rhq.coregui.client.dashboard.portlets.resource;
-import java.util.Arrays; import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.Map;
-import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.smartgwt.client.types.Alignment; -import com.smartgwt.client.types.ContentsType; -import com.smartgwt.client.types.Overflow; -import com.smartgwt.client.types.VerticalAlignment; -import com.smartgwt.client.widgets.Canvas; -import com.smartgwt.client.widgets.HTMLFlow; import com.smartgwt.client.widgets.form.DynamicForm; -import com.smartgwt.client.widgets.form.fields.CanvasItem; -import com.smartgwt.client.widgets.form.fields.LinkItem; -import com.smartgwt.client.widgets.form.fields.StaticTextItem; -import com.smartgwt.client.widgets.form.fields.events.ClickEvent; -import com.smartgwt.client.widgets.form.fields.events.ClickHandler; import com.smartgwt.client.widgets.layout.VLayout;
import org.rhq.core.domain.common.EntityContext; @@ -50,7 +35,6 @@ import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowCo import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.composite.ResourceComposite; -import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.coregui.client.LinkManager; import org.rhq.coregui.client.dashboard.Portlet; @@ -61,9 +45,7 @@ import org.rhq.coregui.client.inventory.common.detail.summary.AbstractActivityVi import org.rhq.coregui.client.inventory.common.graph.CustomDateRangeState; import org.rhq.coregui.client.inventory.resource.detail.monitoring.D3GraphListView; import org.rhq.coregui.client.inventory.resource.type.ResourceTypeRepository; -import org.rhq.coregui.client.util.BrowserUtility; import org.rhq.coregui.client.util.Log; -import org.rhq.coregui.client.util.async.Command; import org.rhq.coregui.client.util.async.CountDownLatch;
/** @@ -77,18 +59,14 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet { public static final String KEY = "ResourceMetrics"; // A default displayed, persisted name for the portlet public static final String NAME = MSG.view_portlet_defaultName_resource_metrics(); - - private int resourceId = -1;
- private ChartViewWindow window; - private D3GraphListView graphView; + private int resourceId = -1;
public ResourceMetricsPortlet(int resourceId) { super(EntityContext.forResource(-1)); this.resourceId = resourceId; } - - private volatile List<MeasurementSchedule> enabledSchedules = null; + private volatile Resource resource = null;
public static final class Factory implements PortletViewFactory { @@ -104,37 +82,54 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet { } }
- /** Fetches recent metric information and updates the DynamicForm instance with i)sparkline information, - * ii) link to recent metric graph for more details and iii) last metric value formatted to show significant - * digits. - */ @Override - protected void getRecentMetrics() { - - //display container - final VLayout column = new VLayout(); - column.setHeight(10);//pack - column.setWidth100(); - - final CountDownLatch latch = CountDownLatch.create(2, new Command() { - - @Override - public void execute() { - showEnabledMetrics(enabledSchedules == null ? null : getEnabledDefinitions(enabledSchedules), column, resource); - } - - private Set<MeasurementDefinition> getEnabledDefinitions(List<MeasurementSchedule> enabledSchedules) { - Set<MeasurementDefinition> enabledDefinitions = new HashSet<MeasurementDefinition>(enabledSchedules.size()); - for (MeasurementSchedule schedule : enabledSchedules) { - enabledDefinitions.add(schedule.getDefinition()); + protected void showPopupWithChart(String title, MeasurementDefinition md) { + ChartViewWindow window = new ChartViewWindow(title, "", refreshablePortlet); + D3GraphListView graphView = D3GraphListView.createSingleGraph(resource, md.getId(), true); + window.addItem(graphView); + window.show(); + } + + @Override + protected DynamicForm getEmptyDataForm() { + return AbstractActivityView.createEmptyDisplayRow(AbstractActivityView.RECENT_MEASUREMENTS_NONE); + } + + @Override + protected String getSeeMoreLink() { + return LinkManager.getResourceMonitoringGraphsLink(resourceId); + } + + @Override + protected MeasurementScheduleCriteria addFilterKey(MeasurementScheduleCriteria criteria) { + criteria.addFilterResourceId(resourceId); + return criteria; + } + + @Override + protected void fetchEnabledMetrics(List<MeasurementSchedule> schedules, int[] definitionArrayIds, + final String[] displayOrder, final Map<String, MeasurementDefinition> measurementDefMap, final VLayout layout) { + GWTServiceLookup.getMeasurementDataService().findDataForResource(resourceId, definitionArrayIds, + CustomDateRangeState.getInstance().getStartTime(), CustomDateRangeState.getInstance().getEndTime(), 60, + new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() { + @Override + public void onFailure(Throwable caught) { + Log.debug("Error retrieving recent metrics charting data for resource [" + resourceId + "]:" + + caught.getMessage()); + setRefreshing(false); + } + + @Override + public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> results) { + renderData(results, displayOrder, measurementDefMap, layout); } - return enabledDefinitions; } - }); - - //fetch only enabled schedules - fetchEnabledSchedules(latch);
+ ); + } + + @Override + protected void fetchResourceType(final CountDownLatch latch, final VLayout layout) { //locate resource reference ResourceCriteria criteria = new ResourceCriteria(); criteria.addFilterId(this.resourceId); @@ -170,192 +165,5 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet { } } }); - - //cleanup - for (Canvas child : recentMeasurementsContent.getChildren()) { - child.destroy(); - } - recentMeasurementsContent.addChild(column); - recentMeasurementsContent.markForRedraw(); - } - - private void fetchEnabledSchedules(final CountDownLatch latch) { - MeasurementScheduleCriteria criteria = new MeasurementScheduleCriteria(); - criteria.addFilterResourceId(resourceId); - criteria.addFilterEnabled(true); - criteria.fetchDefinition(true); - criteria.setPageControl(PageControl.getUnlimitedInstance()); - GWTServiceLookup.getMeasurementDataService().findMeasurementSchedulesByCriteria(criteria, new AsyncCallback<PageList<MeasurementSchedule>>() { - - @Override - public void onSuccess(PageList<MeasurementSchedule> result) { - enabledSchedules = result; - latch.countDown(); - } - - @Override - public void onFailure(Throwable caught) { - latch.countDown(); - } - }); - } - - - private void showEnabledMetrics(final Set<MeasurementDefinition> definitions, final VLayout layout, final Resource resource) { - if (resource == null || definitions == null) { - Log.warn("Unable to render recent metrics properly."); - return; - } - - //build id mapping for measurementDefinition instances Ex. Free Memory -> MeasurementDefinition[100071] - final HashMap<String, MeasurementDefinition> measurementDefMap = new HashMap<String, MeasurementDefinition>(); - for (MeasurementDefinition definition : definitions) { - measurementDefMap.put(definition.getDisplayName(), definition); - } - //bundle definition ids for async call. - int[] definitionArrayIds = new int[definitions.size()]; - final String[] displayOrder = new String[definitions.size()]; - measurementDefMap.keySet().toArray(displayOrder); - //sort the charting data ex. Free Memory, Free Swap Space,..System Load - Arrays.sort(displayOrder); - - //organize definitionArrayIds for ordered request on server. - int index = 0; - for (String definitionToDisplay : displayOrder) { - definitionArrayIds[index++] = measurementDefMap.get(definitionToDisplay).getId(); - } - - GWTServiceLookup.getMeasurementDataService().findDataForResource(resourceId, definitionArrayIds, - CustomDateRangeState.getInstance().getStartTime(), CustomDateRangeState.getInstance().getEndTime(), 60, - new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() { - @Override - public void onFailure(Throwable caught) { - Log.debug("Error retrieving recent metrics charting data for resource [" + resourceId + "]:" - + caught.getMessage()); - setRefreshing(false); - } - - @Override - public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> results) { - if (!results.isEmpty()) { - boolean someChartedData = false; - //iterate over the retrieved charting data - for (int index = 0; index < displayOrder.length; index++) { - //retrieve the correct measurement definition - final MeasurementDefinition md = measurementDefMap.get(displayOrder[index]); - - //load the data results for the given metric definition - List<MeasurementDataNumericHighLowComposite> data = results.get(index); - - //locate last and minimum values. - double lastValue = -1; - double minValue = Double.MAX_VALUE;// - for (MeasurementDataNumericHighLowComposite d : data) { - if ((!Double.isNaN(d.getValue())) && (!String.valueOf(d.getValue()).contains("NaN"))) { - if (d.getValue() < minValue) { - minValue = d.getValue(); - } - lastValue = d.getValue(); - } - } - - //collapse the data into comma delimited list for consumption by third party javascript library(jquery.sparkline) - String commaDelimitedList = ""; - - for (MeasurementDataNumericHighLowComposite d : data) { - if ((!Double.isNaN(d.getValue())) && (!String.valueOf(d.getValue()).contains("NaN"))) { - commaDelimitedList += d.getValue() + ","; - } - } - DynamicForm row = new DynamicForm(); - row.setNumCols(3); - row.setColWidths(65, "*", 100); - row.setWidth100(); - row.setAutoHeight(); - row.setOverflow(Overflow.VISIBLE); - HTMLFlow sparklineGraph = new HTMLFlow(); - String contents = "<span id='sparkline_" + index + "' class='dynamicsparkline' width='0' " - + "values='" + commaDelimitedList + "'>...</span>"; - sparklineGraph.setContents(contents); - sparklineGraph.setContentsType(ContentsType.PAGE); - //disable scrollbars on span - sparklineGraph.setScrollbarSize(0); - - CanvasItem sparklineContainer = new CanvasItem(); - sparklineContainer.setShowTitle(false); - sparklineContainer.setHeight(16); - sparklineContainer.setWidth(60); - sparklineContainer.setCanvas(sparklineGraph); - - //Link/title element - final String title = md.getDisplayName(); - LinkItem link = AbstractActivityView.newLinkItem(title, null); - link.setTooltip(title); - link.setTitleVAlign(VerticalAlignment.TOP); - link.setAlign(Alignment.LEFT); - link.setClipValue(true); - link.setWrap(true); - link.setHeight(26); - link.setWidth("100%"); - if (!BrowserUtility.isBrowserPreIE9()) { - link.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - window = new ChartViewWindow(title, "", refreshablePortlet); - - graphView = D3GraphListView.createSingleGraph(resource, md.getId(), true); - - window.addItem(graphView); - window.show(); - } - }); - } else { - link.disable(); - } - - //Value - String convertedValue; - convertedValue = AbstractActivityView.convertLastValueForDisplay(lastValue, md); - StaticTextItem value = AbstractActivityView.newTextItem(convertedValue); - value.setVAlign(VerticalAlignment.TOP); - value.setAlign(Alignment.RIGHT); - - row.setItems(sparklineContainer, link, value); - row.setWidth100(); - - //if graph content returned - if ((!md.getName().trim().contains("Trait.")) && (lastValue != -1)) { - layout.addMember(row); - someChartedData = true; - } - } - if (!someChartedData) {// when there are results but no chartable entries. - DynamicForm row = AbstractActivityView.createEmptyDisplayRow( - - AbstractActivityView.RECENT_MEASUREMENTS_NONE); - layout.addMember(row); - } else { - //insert see more link - DynamicForm row = new DynamicForm(); - String link = LinkManager.getResourceMonitoringGraphsLink(resourceId); - AbstractActivityView.addSeeMoreLink(row, link, layout); - } - //call out to 3rd party javascript lib - new Timer() { - @Override - public void run() { - BrowserUtility.graphSparkLines(); - } - }.schedule(200); - } else { - DynamicForm row = AbstractActivityView - .createEmptyDisplayRow(AbstractActivityView.RECENT_MEASUREMENTS_NONE); - layout.addMember(row); - } - setRefreshing(false); - } - } - - ); } }