Mercurial > hg > release > thermostat-0.7
changeset 743:19cb0438ff2e
Eclipse VM CPU chart
This commit adds a new view in Eclipse for monitoring a VM's CPU, similar
to the VM's CPU tab in the Swing GUI.
Reviewed-by: jerboaa
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-September/003351.html
line wrap: on
line diff
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java Thu Oct 25 13:35:41 2012 -0400 +++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java Thu Oct 25 13:36:43 2012 -0400 @@ -55,7 +55,7 @@ import com.redhat.thermostat.common.model.DiscreteTimeData; import com.redhat.thermostat.common.model.VmCpuStat; -class VmCpuController { +public class VmCpuController { private final VmRef ref; private final VmCpuStatDAO dao;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/SWTVmCpuView.java Thu Oct 25 13:36:43 2012 -0400 @@ -0,0 +1,132 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.eclipse.chart.common; + +import java.awt.EventQueue; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.data.time.FixedMillisecond; +import org.jfree.data.time.RegularTimePeriod; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; + +import com.redhat.thermostat.client.core.views.VmCpuView; +import com.redhat.thermostat.client.locale.LocaleResources; +import com.redhat.thermostat.common.locale.Translate; +import com.redhat.thermostat.common.model.DiscreteTimeData; +import com.redhat.thermostat.eclipse.ThermostatConstants; +import com.redhat.thermostat.eclipse.views.SWTComponent; + +public class SWTVmCpuView extends VmCpuView implements SWTComponent { + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + private final TimeSeriesCollection data; + private final TimeSeries cpuTimeSeries; + + private JFreeChart chart; + private ViewVisibilityWatcher watcher; + + public SWTVmCpuView() { + data = new TimeSeriesCollection(); + cpuTimeSeries = new TimeSeries("cpu-stats"); + watcher = new ViewVisibilityWatcher(notifier); + chart = createCpuChart(); + + data.addSeries(cpuTimeSeries); + } + + public void createControl(Composite parent) { + Composite chartTop = new RecentTimeSeriesChartComposite(parent, SWT.NONE, chart); + chartTop.setLayout(new GridLayout()); + chartTop.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + watcher.watch(parent, ThermostatConstants.VIEW_ID_VM_CPU); + } + + private JFreeChart createCpuChart() { + JFreeChart chart = ChartFactory.createTimeSeriesChart( + null, + translator.localize(LocaleResources.VM_CPU_CHART_TIME_LABEL), + translator.localize(LocaleResources.VM_CPU_CHART_LOAD_LABEL), + data, + false, false, false); + + chart.getXYPlot().getRangeAxis().setLowerBound(0.0); + + return chart; + } + + @Override + public void addData(List<DiscreteTimeData<? extends Number>> data) { + final List<DiscreteTimeData<? extends Number>> copy = new ArrayList<>(data); + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + for (DiscreteTimeData<? extends Number> data: copy) { + RegularTimePeriod period = new FixedMillisecond(data.getTimeInMillis()); + if (cpuTimeSeries.getDataItem(period) == null) { + cpuTimeSeries.add(period, data.getData(), false); + } + } + cpuTimeSeries.fireSeriesChanged(); + } + }); + } + + @Override + public void clearData() { + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + cpuTimeSeries.clear(); + } + }); + } + + public JFreeChart getChart() { + return chart; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/SWTVmCpuViewProvider.java Thu Oct 25 13:36:43 2012 -0400 @@ -0,0 +1,49 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.eclipse.chart.common; + +import com.redhat.thermostat.client.core.views.VmCpuView; +import com.redhat.thermostat.client.core.views.VmCpuViewProvider; + +public class SWTVmCpuViewProvider implements VmCpuViewProvider { + + @Override + public VmCpuView createView() { + return new SWTVmCpuView(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/VmCpuViewPart.java Thu Oct 25 13:36:43 2012 -0400 @@ -0,0 +1,66 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.eclipse.chart.common; + +import com.redhat.thermostat.client.core.views.VmCpuViewProvider; +import com.redhat.thermostat.client.ui.VmCpuController; +import com.redhat.thermostat.common.dao.VmCpuStatDAO; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.common.utils.OSGIUtils; +import com.redhat.thermostat.eclipse.views.SWTComponent; + +public class VmCpuViewPart extends VmRefViewPart { + + private VmCpuController controller; + + @Override + protected void createControllerView(VmRef ref) { + VmCpuStatDAO vmCpuStatDao = OSGIUtils.getInstance().getService( + VmCpuStatDAO.class); + VmCpuViewProvider viewProvider = OSGIUtils.getInstance().getService( + VmCpuViewProvider.class); + controller = createController(vmCpuStatDao, ref, viewProvider); + SWTComponent view = (SWTComponent) controller.getView(); + view.createControl(top); + } + + public VmCpuController createController(VmCpuStatDAO vmCpuStatDao, + VmRef ref, VmCpuViewProvider viewProvider) { + return new VmCpuController(vmCpuStatDao, ref, viewProvider); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eclipse/com.redhat.thermostat.eclipse.test.ui/src/com/redhat/thermostat/eclipse/test/ui/SWTVmCpuViewTest.java Thu Oct 25 13:36:43 2012 -0400 @@ -0,0 +1,166 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.eclipse.test.ui; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.swt.finder.waits.DefaultCondition; +import org.jfree.chart.JFreeChart; +import org.jfree.data.xy.XYDataset; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.model.DiscreteTimeData; +import com.redhat.thermostat.eclipse.chart.common.SWTVmCpuView; + +public class SWTVmCpuViewTest { + private SWTWorkbenchBot bot; + private SWTVmCpuView view; + private Shell shell; + + @Before + public void beforeTest() throws Exception { + bot = new SWTWorkbenchBot(); + + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() { + shell = new Shell(Display.getCurrent()); + Composite parent = new Composite(shell, SWT.NONE); + parent.setLayout(new GridLayout()); + parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, + true)); + view = new SWTVmCpuView(); + view.createControl(parent); + shell.open(); + } + }); + } + + @After + public void afterTest() throws Exception { + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() { + if (shell != null) { + shell.close(); + view = null; + } + } + }); + } + + @Test + public void testAddData() { + List<DiscreteTimeData<? extends Number>> data = new ArrayList<DiscreteTimeData<? extends Number>>(); + + data.add(new DiscreteTimeData<Number>(1000L, 20)); + data.add(new DiscreteTimeData<Number>(2000L, 80)); + data.add(new DiscreteTimeData<Number>(3000L, 50)); + + addSeries(data); + + JFreeChart chart = view.getChart(); + XYDataset dataset = chart.getXYPlot().getDataset(); + assertEquals(1000L, dataset.getX(0, 0)); + assertEquals(2000L, dataset.getX(0, 1)); + assertEquals(3000L, dataset.getX(0, 2)); + + assertEquals(20, dataset.getY(0, 0)); + assertEquals(80, dataset.getY(0, 1)); + assertEquals(50, dataset.getY(0, 2)); + } + + private void addSeries(List<DiscreteTimeData<? extends Number>> data) { + view.addData(data); + + bot.waitUntil(new DefaultCondition() { + + @Override + public boolean test() throws Exception { + JFreeChart chart = view.getChart(); + return chart.getXYPlot().getDataset().getItemCount(0) == 3; + } + + @Override + public String getFailureMessage() { + return "Data never added"; + } + }); + } + + @Test + public void testClearData() { + List<DiscreteTimeData<? extends Number>> data = new ArrayList<DiscreteTimeData<? extends Number>>(); + + data.add(new DiscreteTimeData<Number>(1000L, 20)); + data.add(new DiscreteTimeData<Number>(2000L, 80)); + data.add(new DiscreteTimeData<Number>(3000L, 50)); + + addSeries(data); + + view.clearData(); + + bot.waitUntil(new DefaultCondition() { + + @Override + public boolean test() throws Exception { + JFreeChart chart = view.getChart(); + return chart.getXYPlot().getDataset().getItemCount(0) == 0; + } + + @Override + public String getFailureMessage() { + return "Data never cleared"; + } + }); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmCpuViewPartTest.java Thu Oct 25 13:36:43 2012 -0400 @@ -0,0 +1,106 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat 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; either version 2, or (at your + * option) any later version. + * + * Thermostat 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 Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.eclipse.test.views; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Composite; +import org.junit.Test; + +import com.redhat.thermostat.client.core.views.VmCpuViewProvider; +import com.redhat.thermostat.client.ui.VmCpuController; +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.common.dao.VmCpuStatDAO; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.eclipse.chart.common.RefViewPart; +import com.redhat.thermostat.eclipse.chart.common.SWTVmCpuView; +import com.redhat.thermostat.eclipse.chart.common.VmCpuViewPart; + +public class VmCpuViewPartTest extends AbstractRefViewPartTest<VmRef> { + + @Test + public void testSelectionHostRef() throws Exception { + view.createPartControl(parent); + + HostRef hostRef = new HostRef("TEST", "Test"); + IStructuredSelection selection = mockSelection(hostRef); + view.selectionChanged(hostVMView, selection); + + // Ensure not created + verify(thermoView, never()).createControl(any(Composite.class)); + } + + @Test + public void testSelectionAfter() throws Exception { + view.createPartControl(parent); + + HostRef hostRef = new HostRef("TEST", "Test"); + VmRef vmRef = new VmRef(hostRef, 0, "Test"); + IStructuredSelection selection = mockSelection(vmRef); + view.selectionChanged(hostVMView, selection); + + verify(thermoView).createControl(any(Composite.class)); + } + + @Override + protected void mockController() { + VmCpuController controller = mock(VmCpuController.class); + thermoView = mock(SWTVmCpuView.class); + + VmCpuStatDAO cpuStatDao = mock(VmCpuStatDAO.class); + VmCpuViewProvider viewProvider = mock(VmCpuViewProvider.class); + when(osgi.getService(VmCpuStatDAO.class)).thenReturn(cpuStatDao); + when(osgi.getService(VmCpuViewProvider.class)).thenReturn(viewProvider); + + doReturn(controller).when(((VmCpuViewPart) view)).createController( + same(cpuStatDao), any(VmRef.class), same(viewProvider)); + when(controller.getView()).thenReturn(thermoView); + } + + @Override + protected RefViewPart<VmRef> createViewPart() { + return new VmCpuViewPart(); + } + +}