/* * RHQ Management Platform * Copyright (C) 2005-2015 Red Hat, Inc. * All rights reserved. * * 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 */ package org.rhq.coregui.client.dashboard.portlets.resource; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.widgets.form.fields.FloatItem; import com.smartgwt.client.widgets.form.fields.LinkItem; import com.smartgwt.client.widgets.form.fields.PickerIcon; import com.smartgwt.client.widgets.form.fields.StaticTextItem; import com.smartgwt.client.widgets.form.fields.events.BlurEvent; import com.smartgwt.client.widgets.form.fields.events.BlurHandler; import com.smartgwt.client.widgets.form.fields.events.ClickEvent; import com.smartgwt.client.widgets.form.fields.events.ClickHandler; import com.smartgwt.client.widgets.form.fields.events.FormItemClickHandler; import com.smartgwt.client.widgets.form.fields.events.FormItemIconClickEvent; import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent; import com.smartgwt.client.widgets.form.fields.events.KeyUpHandler; import org.rhq.core.domain.measurement.MeasurementBaseline; import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.measurement.MeasurementUnits; import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits; import org.rhq.core.domain.resource.Resource; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.components.form.EnhancedDynamicForm; import org.rhq.coregui.client.dashboard.portlets.groups.GroupMetricsPortlet; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.inventory.common.detail.summary.AbstractActivityView; import org.rhq.coregui.client.inventory.resource.detail.monitoring.D3GraphListView; import org.rhq.coregui.client.util.Log; import org.rhq.coregui.client.util.MeasurementConverterClient; import org.rhq.coregui.client.util.enhanced.Enhanced; import org.rhq.coregui.client.util.measurement.GwtMonitorUtils; import org.rhq.coregui.client.util.message.Message; /** * Metrics chart Window with Baseline editing capabilities. */ public class MetricsChartWindow implements Enhanced { public static final String CHANGE_VALUE = MSG.chart_baseline_change_value_label(); private static final String BASELINE_SECTION_TITLE = MSG.chart_baseline_section_title(); private static final String BASELINE_MEAN = MSG.chart_baseline_baseline_mean(); private static final String NEW_BASELINE_MEAN = MSG.chart_baseline_baseline_mean_new(); private static final String BASELINE_HIGH = MSG.chart_baseline_baseline_high(); private static final String NEW_BASELINE_HIGH = MSG.chart_baseline_baseline_high_new(); private static final String BASELINE_LOW = MSG.chart_baseline_baseline_low(); private static final String NEW_BASELINE_LOW = MSG.chart_baseline_baseline_low_new(); private static final String CUSTOM_USER_BASELINE_MEAN_WAS_NOT_SAVED = MSG.chart_baseline_mean_not_saved(); private static final String CUSTOM_USER_BASELINE_MEAN_SUCCESSFULLY_SAVED = MSG.chart_baseline_mean_saved(); private static final String CUSTOM_USER_BASELINE_HIGH_WAS_NOT_SAVED = MSG.chart_baseline_high_not_saved(); private static final String CUSTOM_USER_BASELINE_HIGH_BOUND_SUCCESSFULLY_SAVED = MSG.chart_baseline_high_saved(); private static final String CUSTOM_USER_BASELINE_LOW_WAS_NOT_SAVED = MSG.chart_baseline_low_not_saved(); private static final String CUSTOM_USER_BASELINE_LOW_BOUND_SUCCESSFULLY_SAVED = MSG.chart_baseline_low_saved(); private StaticTextItem baselineText; private StaticTextItem expectedRangeHighText; private StaticTextItem expectedRangeLowText; private FloatItem newBaselineMeanText; private FloatItem newExpectedRangeHighText; private FloatItem newExpectedRangeLowText; private MeasurementNumericValueAndUnits baselineMeanMd; private MeasurementNumericValueAndUnits baselineHighMd; private MeasurementNumericValueAndUnits baselineLowMd; private MeasurementDefinition measurementDefinition; private int resourceId = -1; public MetricsChartWindow() { baselineText = new StaticTextItem(); expectedRangeHighText = new StaticTextItem(); expectedRangeLowText = new StaticTextItem(); newBaselineMeanText = new FloatItem(); newBaselineMeanText.setKeyPressFilter("[0-9.]"); newExpectedRangeHighText = new FloatItem(); newExpectedRangeHighText.setKeyPressFilter("[0-9.]"); newExpectedRangeLowText = new FloatItem(); newExpectedRangeLowText.setKeyPressFilter("[0-9.]"); } private EnhancedDynamicForm createMetricBaselineForm() { EnhancedDynamicForm metricsBaselineForm = new EnhancedDynamicForm(); metricsBaselineForm.setGroupTitle(BASELINE_SECTION_TITLE); metricsBaselineForm.setIsGroup(true); metricsBaselineForm.setExtraSpace(10); metricsBaselineForm.setNumCols(3); metricsBaselineForm.setColWidths(200, 80, "*"); metricsBaselineForm.setCellPadding(3); metricsBaselineForm.setWidth("95%"); // Baseline baselineText.setTitle(BASELINE_MEAN); LinkItem baselineLink = AbstractActivityView.newLinkItem(CHANGE_VALUE, null); baselineLink.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent clickEvent) { newBaselineMeanText.show(); newBaselineMeanText.setSelectOnFocus(true); newExpectedRangeHighText.hide(); newExpectedRangeLowText.hide(); } }); newBaselineMeanText.setTitle(NEW_BASELINE_MEAN); newBaselineMeanText.addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent blurEvent) { hideBaselineEditingFields(); } }); PickerIcon cancelPicker = new PickerIcon(PickerIcon.CLEAR, new FormItemClickHandler() { public void onFormItemClick(FormItemIconClickEvent event) { hideBaselineEditingFields(); } }); newBaselineMeanText.setIcons(cancelPicker); newBaselineMeanText.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent keyUpEvent) { if (keyUpEvent.getKeyName().equals("Enter")) { hideBaselineEditingFields(); if (null != newBaselineMeanText.getValueAsString()) { double newBaselineMean = Double.parseDouble(newBaselineMeanText.getValueAsString()); saveCustomBaselineMean(newBaselineMean); } } } }); // High Baseline expectedRangeHighText.setTitle(BASELINE_HIGH); LinkItem baselineHighLink = AbstractActivityView.newLinkItem(CHANGE_VALUE, null); baselineHighLink.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent clickEvent) { // High cannot be below the low newBaselineMeanText.hide(); newExpectedRangeHighText.show(); newExpectedRangeHighText.setSelectOnFocus(true); newExpectedRangeLowText.hide(); } }); newExpectedRangeHighText.setTitle(NEW_BASELINE_HIGH); newExpectedRangeHighText.addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent blurEvent) { hideBaselineEditingFields(); } }); newExpectedRangeHighText.setIcons(cancelPicker); newExpectedRangeHighText.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent keyUpEvent) { if (keyUpEvent.getKeyName().equals("Enter")) { hideBaselineEditingFields(); if (null != newExpectedRangeHighText.getValueAsString()) { double newBaselineHigh = Double.parseDouble(newExpectedRangeHighText.getValueAsString()); saveCustomBaselineHigh(newBaselineHigh); } } } }); // Low Baseline expectedRangeLowText.setTitle(BASELINE_LOW); LinkItem baselineLowLink = AbstractActivityView.newLinkItem(CHANGE_VALUE, null); baselineLowLink.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent clickEvent) { newBaselineMeanText.hide(); newExpectedRangeHighText.hide(); newExpectedRangeLowText.show(); newExpectedRangeLowText.setSelectOnFocus(true); } }); newExpectedRangeLowText.setTitle(NEW_BASELINE_LOW); newExpectedRangeLowText.addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent blurEvent) { hideBaselineEditingFields(); } }); newExpectedRangeLowText.setIcons(cancelPicker); newExpectedRangeLowText.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent keyUpEvent) { if (keyUpEvent.getKeyName().equals("Enter")) { hideBaselineEditingFields(); if (null != newExpectedRangeLowText.getValueAsString()) { double newBaselineLow = Double.parseDouble(newExpectedRangeLowText.getValueAsString()); saveCustomBaselineLow(newBaselineLow); } } } }); //@hack: the only way to hide is to wait a while for them to appear created in the DOM new Timer() { @Override public void run() { hideBaselineEditingFields(); } }.schedule(150); metricsBaselineForm.setFields(baselineText, baselineLink, newBaselineMeanText, expectedRangeHighText, baselineHighLink, newExpectedRangeHighText, expectedRangeLowText, baselineLowLink, newExpectedRangeLowText); return metricsBaselineForm; } private void saveCustomBaselineMean(double newBaselineMean) { Log.debug("Saving baseline mean: " + newBaselineMean); Double scaledValue = MeasurementConverterClient.scale(new MeasurementNumericValueAndUnits(newBaselineMean, baselineMeanMd.getUnits()), MeasurementUnits.BYTES); GWTServiceLookup.getMeasurementDataService().setUserBaselineMean(resourceId, measurementDefinition.getId(), scaledValue, new AsyncCallback<Void>() { @Override public void onFailure(Throwable throwable) { unSuccessfulSave(CUSTOM_USER_BASELINE_MEAN_WAS_NOT_SAVED, throwable); } @Override public void onSuccess(Void aVoid) { successfulSave(CUSTOM_USER_BASELINE_MEAN_SUCCESSFULLY_SAVED); } }); } private void saveCustomBaselineHigh(double newBaselineHigh) { Log.debug("Saving baseline high: " + newBaselineHigh); Double scaledValue = MeasurementConverterClient.scale(new MeasurementNumericValueAndUnits(newBaselineHigh, baselineHighMd.getUnits()), MeasurementUnits.BYTES); GWTServiceLookup.getMeasurementDataService().setUserBaselineMax(resourceId, measurementDefinition.getId(), scaledValue, new AsyncCallback<Void>() { @Override public void onFailure(Throwable throwable) { unSuccessfulSave(CUSTOM_USER_BASELINE_HIGH_WAS_NOT_SAVED, throwable); } @Override public void onSuccess(Void aVoid) { successfulSave(CUSTOM_USER_BASELINE_HIGH_BOUND_SUCCESSFULLY_SAVED); } }); } private void saveCustomBaselineLow(double newBaselineLow) { Log.debug("Saving baseline low: " + newBaselineLow); Double scaledValue = MeasurementConverterClient.scale(new MeasurementNumericValueAndUnits(newBaselineLow, baselineLowMd.getUnits()), MeasurementUnits.BYTES); GWTServiceLookup.getMeasurementDataService().setUserBaselineMin(resourceId, measurementDefinition.getId(), scaledValue, new AsyncCallback<Void>() { @Override public void onFailure(Throwable throwable) { unSuccessfulSave(CUSTOM_USER_BASELINE_LOW_WAS_NOT_SAVED, throwable); } @Override public void onSuccess(Void aVoid) { successfulSave(CUSTOM_USER_BASELINE_LOW_BOUND_SUCCESSFULLY_SAVED); } }); } private void successfulSave(String successMessage) { Log.debug(successMessage); CoreGUI.getMessageCenter().notify(new Message(successMessage, Message.Severity.Info)); hideBaselineEditingFields(); queryScheduleBaseline(resourceId, measurementDefinition); } private void unSuccessfulSave(String failureMessage, Throwable throwable) { Log.warn(failureMessage, throwable); CoreGUI.getMessageCenter().notify(new Message(failureMessage, throwable, Message.Severity.Error)); } public void showPopupChart(String title, Resource resource, MeasurementDefinition measurementDefinition, GroupMetricsPortlet refreshablePortlet) { this.measurementDefinition = measurementDefinition; resourceId = resource.getId(); GroupMetricsPortlet.ChartViewWindow window = new GroupMetricsPortlet.ChartViewWindow(title, "", refreshablePortlet); D3GraphListView graphView = D3GraphListView.createSingleGraph(resource, measurementDefinition.getId(), true); window.addItem(graphView); window.addItem(createMetricBaselineForm()); window.show(); queryScheduleBaseline(resourceId, measurementDefinition); } private void hideBaselineEditingFields() { newBaselineMeanText.hide(); newExpectedRangeHighText.hide(); newExpectedRangeLowText.hide(); } private void queryScheduleBaseline(final int resourceId, final MeasurementDefinition md) { GWTServiceLookup.getMeasurementDataService().getBaselineForResourceAndSchedule(resourceId, md.getId(), new AsyncCallback<MeasurementBaseline>() { public void onSuccess(MeasurementBaseline measurementBaseline) { if (null != measurementBaseline) { MeasurementUnits units = md.getUnits(); baselineText.setValue(GwtMonitorUtils.formatSimpleMetric(measurementBaseline.getMean(), md)); expectedRangeHighText.setValue(GwtMonitorUtils.formatSimpleMetric(measurementBaseline.getMax(), md)); expectedRangeLowText.setValue(GwtMonitorUtils.formatSimpleMetric(measurementBaseline.getMin(), md)); baselineText.setTitle(baselineText.getTitle()); expectedRangeHighText.setTitle(expectedRangeHighText.getTitle()); expectedRangeLowText.setTitle(expectedRangeLowText.getTitle()); baselineMeanMd = MeasurementConverterClient.fit(measurementBaseline.getMean(), units); baselineHighMd = MeasurementConverterClient.fit(measurementBaseline.getMax(), units); baselineLowMd = MeasurementConverterClient.fit(measurementBaseline.getMin(), units); newExpectedRangeHighText.setValue(baselineHighMd.getValue()); newBaselineMeanText.setValue(baselineMeanMd.getValue()); newExpectedRangeLowText.setValue(baselineLowMd.getValue()); newBaselineMeanText.setTitle(newBaselineMeanText.getTitle()); newExpectedRangeHighText.setTitle(newExpectedRangeHighText.getTitle()); newExpectedRangeLowText.setTitle(newExpectedRangeLowText.getTitle()); } } @Override public void onFailure(Throwable caught) { Log.debug("Error retrieving out of bound metrics baseline for resource [" + resourceId + "," + md.getId() + "]:" + caught.getMessage()); } }); } }