package com.ibm.nmon.gui.chart;
import java.beans.PropertyChangeEvent;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jfree.chart.JFreeChart;
import com.ibm.nmon.gui.chart.builder.LineChartBuilder;
import com.ibm.nmon.gui.chart.builder.LineChartBuilderPlugin;
import com.ibm.nmon.gui.main.NMONVisualizerGui;
import com.ibm.nmon.data.DataSet;
import com.ibm.nmon.data.DataType;
import com.ibm.nmon.data.SubDataType;
import com.ibm.nmon.data.ProcessDataType;
import com.ibm.nmon.data.definition.ExactDataDefinition;
import com.ibm.nmon.data.definition.NamingMode;
import com.ibm.nmon.chart.definition.LineChartDefinition;
import com.ibm.nmon.interval.IntervalListener;
import com.ibm.nmon.interval.Interval;
/**
* Display a time series plot of the selected data.
*/
public final class DataTypeChartPanel extends LineChartPanel implements IntervalListener {
private static final long serialVersionUID = 7780208253045360843L;
private final LineChartBuilder chartBuilder;
private ExactDataDefinition definition;
public DataTypeChartPanel(NMONVisualizerGui gui) {
super(gui, gui.getMainFrame());
chartBuilder = new LineChartBuilder();
chartBuilder.addPlugin(new LineChartBuilderPlugin(gui));
}
public void setData(DataSet data, DataType type) {
setData(data, type, type.getFields());
}
public void setData(DataSet data, DataType type, List<String> fields) {
definition = new ExactDataDefinition(data, type, fields);
displayChart();
}
public DataSet getData() {
return definition == null ? null : definition.getDataSet();
}
@Override
public void setEnabled(boolean enabled) {
if (isEnabled() != enabled) {
super.setEnabled(enabled);
if (enabled) {
gui.addPropertyChangeListener("granularity", this);
gui.getIntervalManager().addListener(this);
chartBuilder.setInterval(gui.getIntervalManager().getCurrentInterval());
chartBuilder.setGranularity(gui.getGranularity());
if (definition != null) {
displayChart();
}
}
else {
gui.removePropertyChangeListener("granularity", this);
gui.getIntervalManager().removeListener(this);
// _super_ => clear chart but not the data
super.clearChart();
}
}
}
@Override
public void clearChart() {
super.clearChart();
this.definition = null;
}
@Override
protected String validateSaveFileName(String filename) {
DataType type = definition.getDataType();
List<String> fields = definition.getMatchingFields(type);
return super.validateSaveFileName(definition.getDataSet().getHostname() + '_' + type.toString()
+ (fields.size() == 1 ? '_' + fields.get(0) : ""));
}
@Override
public void intervalAdded(Interval interval) {}
@Override
public void intervalRemoved(Interval interval) {}
@Override
public void intervalsCleared() {}
@Override
public void currentIntervalChanged(Interval interval) {
chartBuilder.setInterval(interval);
if (getChart() != null) {
displayChart();
}
}
@Override
public void intervalRenamed(Interval interval) {}
@Override
public void propertyChange(PropertyChangeEvent evt) {
super.propertyChange(evt);
if ("granularity".equals(evt.getPropertyName())) {
chartBuilder.setGranularity((Integer) evt.getNewValue());
if (getChart() != null) {
displayChart();
}
}
}
private void displayChart() {
if (isEnabled()) {
long startT = System.nanoTime();
DataSet data = definition.getDataSet();
DataType type = definition.getDataType();
List<String> fields = definition.getMatchingFields(type);
String fieldLabel = "";
String axisLabel = "";
if (fields.size() == 1) {
fieldLabel = " - " + fields.get(0);
axisLabel = getAxisLabel(type, fields.get(0));
}
else {
axisLabel = getAxisLabel(type);
}
boolean percent = true;
if (!type.getName().contains("%")) {
for (String field : fields) {
if (!field.contains("%")) {
percent = false;
break;
}
if (PERCENT_AXIS_EXCEPTIONS.contains(field)) {
percent = false;
break;
}
if ((type.getClass() == ProcessDataType.class) && gui.getBooleanProperty("scaleProcessesByCPUs")) {
percent = false;
break;
}
}
}
LineChartDefinition chartDefinition = new LineChartDefinition("", type + fieldLabel);
chartDefinition.setYAxisLabel(axisLabel);
chartDefinition.setUsePercentYAxis(percent);
setSaveSize(chartDefinition.getWidth(), chartDefinition.getHeight());
chartBuilder.initChart(chartDefinition);
chartBuilder.addLinesForData(definition, data, NamingMode.FIELD);
JFreeChart chart = chartBuilder.getChart();
if (logger.isDebugEnabled()) {
logger.debug("{}: {}-{} chart created in {}ms",
new Object[] { data.getHostname(), type.getId(),
fields.size() == type.getFieldCount() ? '*' : fields,
(System.nanoTime() - startT) / 1000000.0d });
}
setChart(chart);
}
}
private String getAxisLabel(DataType type) {
if ("CPU_ALL".equals(type.getId())) {
return "";
}
else if (type.getId().startsWith("CPU")) {
return "% CPU";
}
else {
String label = TYPE_AXIS_NAMES.get(type.getId());
if (label == null) {
int idx = type.getId().indexOf('(');
if (idx != -1) {
label = TYPE_AXIS_NAMES.get(type.getId().substring(0, idx - 1));
}
}
if (label == null) {
return "";
}
else {
return label;
}
}
}
private String getAxisLabel(DataType type, String field) {
String label = FIELD_AXIS_NAMES.get(field);
if (label != null) {
return label;
}
else if (field.endsWith("kb/s")) {
return "KB / s";
}
else if (field.contains("packets")) {
return "Packets / s";
}
else if (field.startsWith("nr_")) {
return "Count";
}
else if (field.startsWith("pg")) {
return "Pages / s";
}
else if (field.endsWith("ch")) {
return "Characters / s";
}
else if (field.endsWith("_freed")) {
return "MB";
}
else if (field.toLowerCase().contains("megabytes")) {
return "MB";
}
else if (field.toLowerCase().contains("mbytes")) {
return "MB";
}
else if (field.toLowerCase().contains("kbytes")) {
return "KB";
}
else if (field.toLowerCase().contains("bytes")) {
return "Bytes";
}
else if (field.contains("count")) {
return "Count";
}
else if (field.endsWith("kb")) {
return "KB";
}
else if (field.endsWith("mb")) {
return "MB";
}
else {
return getAxisLabel(type);
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
gui.removePropertyChangeListener("granularity", this);
gui.getIntervalManager().removeListener(this);
}
private static final Map<String, String> TYPE_AXIS_NAMES;
private static final Map<String, String> FIELD_AXIS_NAMES;
private static final Set<String> PERCENT_AXIS_EXCEPTIONS;
static {
Map<String, String> tempTypes = new java.util.HashMap<String, String>();
Map<String, String> tempFields = new java.util.HashMap<String, String>();
Set<String> tempExceptions = new java.util.HashSet<String>();
tempTypes.put("DISKBSIZE", "KB / Block");
tempTypes.put("DISKBUSY", "% Busy");
tempTypes.put("DISKREAD", "KB / s");
tempTypes.put("DISKWRITE", "KB / s");
tempTypes.put("DISKRXFER", "IO Ops / s");
tempTypes.put("DISKXFER", "IO Ops / s");
tempTypes.put("JFSFILE", "% Used");
tempTypes.put("JFSINODE", "% Used");
tempTypes.put("MEMNEW", "% Used");
tempTypes.put("NET", "KB / s");
tempTypes.put("NETPACKET", "Packets / s");
tempTypes.put("NETERROR", "Errors / s");
tempTypes.put("NETSIZE", "Bytes / Packet");
tempTypes.put("GCAFT", "MB");
tempTypes.put("GCBEF", "MB");
tempTypes.put("GCSINCE", "Seconds");
tempTypes.put("GCTIME", "Milliseconds");
tempTypes.put("GCCOUNT", "Count");
tempTypes.put("SEA", "KB / s");
tempTypes.put("SEAPACKET", "Packets / s");
tempTypes.put("FCREAD", "KB / s");
tempTypes.put("FCWRITE", "KB / s");
tempTypes.put("FCXFERIN", "Frames / s");
tempTypes.put("FCXFEROUT", "Frames / s");
tempTypes.put("RESP", "Seconds");
tempTypes.put("IOStat CPU", "%");
tempTypes.put(SubDataType.buildId("IOStat Device", "%util"), "% Utilization");
tempTypes.put(SubDataType.buildId("IOStat Device", "rMB/s"), "MB / s");
tempTypes.put(SubDataType.buildId("IOStat Device", "wMB/s"), "MB / s");
tempTypes.put(SubDataType.buildId("IOStat Device", "await"), "ms");
tempTypes.put(SubDataType.buildId("IOStat Device", "r_await"), "ms");
tempTypes.put(SubDataType.buildId("IOStat Device", "w_await"), "ms");
tempTypes.put(SubDataType.buildId("IOStat Device", "svctm"), "ms");
tempTypes.put(SubDataType.buildId("IOStat ZPool", "alloc"), "GB");
tempTypes.put(SubDataType.buildId("IOStat ZPool", "free"), "GB");
tempTypes.put(SubDataType.buildId("IOStat ZPool", "rMB/s"), "MB / s");
tempTypes.put(SubDataType.buildId("IOStat ZPool", "wMB/s"), "MB / s");
tempTypes.put("LAT", "μs");
tempTypes.put("CLAT", "μs");
tempTypes.put("SLAT", "μs");
tempTypes.put("BW", "KB / s");
tempFields.put("CPUs", "Count");
tempFields.put("CPU%", "% CPU");
tempFields.put("User%", "% CPU");
tempFields.put("Sys%", "% CPU");
tempFields.put("Wait%", "% CPU");
tempFields.put("%CPU", "% CPU");
tempFields.put("%Usr", "% CPU");
tempFields.put("%Sys", "% CPU");
tempFields.put("%Wait", "% CPU");
tempFields.put("Runnable", "Count");
tempFields.put("pswitch", "Switches / s");
tempFields.put("syscall", "Calls / s");
tempFields.put("fork", "Forks / s");
tempFields.put("forks", "Forks / s");
tempFields.put("pgfault", "Faults / s");
tempFields.put("pgmajfault", "Faults / s");
tempFields.put("faults", "Faults / s");
tempFields.put("pgpgin", "KB / s");
tempFields.put("pgpout", "KB / s");
tempFields.put("pswpin", "Pages / s");
tempFields.put("pswpout", "Pages / s");
tempFields.put("Paging", "Pages / s");
tempFields.put("Size", "KB");
tempFields.put("ResSet", "KB");
tempFields.put("ResText", "KB");
tempFields.put("ResData", "KB");
tempFields.put("ShdLib", "KB");
tempFields.put("MajorFault", "Pages / s");
tempFields.put("MinorFault", "Pages / s");
tempFields.put("cycles", "Count / s");
tempFields.put("finalizers", "Count");
tempFields.put("soft", "Count");
tempFields.put("weak", "Count");
tempFields.put("phantom", "Count");
tempFields.put("tiltratio", "%");
tempFields.put("requested", "Bytes");
tempFields.put("flipped", "Objects");
tempFields.put("tenured", "Objects");
tempFields.put("moved", "Objects");
tempFields.put("throughput", "Tx / s");
tempFields.put("hits", "Hits / s");
tempExceptions.add("EC_User%");
tempExceptions.add("EC_Sys%");
tempExceptions.add("EC_Wait%");
tempExceptions.add("EC_CPU%");
tempExceptions.add("VP_User%");
tempExceptions.add("VP_Sys%");
tempExceptions.add("VP_Wait%");
tempExceptions.add("VP_CPU%");
TYPE_AXIS_NAMES = java.util.Collections.unmodifiableMap(tempTypes);
FIELD_AXIS_NAMES = java.util.Collections.unmodifiableMap(tempFields);
PERCENT_AXIS_EXCEPTIONS = java.util.Collections.unmodifiableSet(tempExceptions);
}
}