Author: [log in to unmask] Date: Mon Mar 16 14:42:56 2015 New Revision: 2466 Log: Cleanup ET system strip chart code. Modified: java/trunk/monitoring-util/src/main/java/org/hps/monitoring/plotting/MonitoringPlotFactory.java java/trunk/monitoring-util/src/main/java/org/hps/monitoring/plotting/StripChartBuilder.java java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/SystemStatistics.java java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/SystemStatisticsImpl.java java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/et/EtSystemStripCharts.java Modified: java/trunk/monitoring-util/src/main/java/org/hps/monitoring/plotting/MonitoringPlotFactory.java ============================================================================= --- java/trunk/monitoring-util/src/main/java/org/hps/monitoring/plotting/MonitoringPlotFactory.java (original) +++ java/trunk/monitoring-util/src/main/java/org/hps/monitoring/plotting/MonitoringPlotFactory.java Mon Mar 16 14:42:56 2015 @@ -164,7 +164,7 @@ RegularTimePeriod timeBase, ValueProvider valueProvider, long rangeView) { - StripChartUpdater updater = StripChartBuilder.createStripChart( + StripChartUpdater updater = StripChartBuilder.createDynamicTimeSeriesChart( name, rangeLabel, seriesCount, @@ -216,6 +216,17 @@ return stripChart; } + public JFreeChart createTimeSeriesChart( + String title, + String yAxisLabel, + int seriesCount, + String[] datasetNames, + double rangeSize) { + JFreeChart chart = StripChartBuilder.createTimeSeriesChart(title, yAxisLabel, seriesCount, datasetNames, rangeSize); + addChart(chart); + return chart; + } + /** * Get the global registry of plotters. * @return The global plotter registry. Modified: java/trunk/monitoring-util/src/main/java/org/hps/monitoring/plotting/StripChartBuilder.java ============================================================================= --- java/trunk/monitoring-util/src/main/java/org/hps/monitoring/plotting/StripChartBuilder.java (original) +++ java/trunk/monitoring-util/src/main/java/org/hps/monitoring/plotting/StripChartBuilder.java Mon Mar 16 14:42:56 2015 @@ -26,12 +26,12 @@ * @param valueProvider The interface for providing values. * @return The StripChartUpdater for the chart. */ - static StripChartUpdater createStripChart( + static StripChartUpdater createDynamicTimeSeriesChart( String name, int seriesCount, RegularTimePeriod timeBase, ValueProvider valueProvider) { - return createStripChart(name, "Values", seriesCount, null, 9999, timeBase, valueProvider, 10000L); + return createDynamicTimeSeriesChart(name, "Values", seriesCount, null, 9999, timeBase, valueProvider, 10000L); } /** @@ -47,7 +47,7 @@ * @param rangeView The view in the domain axis around the current data point (milliseconds). * @return The StripChartUpdater for the chart. */ - static StripChartUpdater createStripChart( + static StripChartUpdater createDynamicTimeSeriesChart( String name, String rangeLabel, int seriesCount, @@ -99,7 +99,7 @@ * @param maxCount The maximum count of items in the single data set series. * @return The chart that was created. */ - public static JFreeChart createTimeSeriesChart( + static JFreeChart createTimeSeriesChart( String title, String yAxisLabel, int maxAge, @@ -149,7 +149,7 @@ * @param rangeSize The range of values to show for auto-ranging in domain axis (in milliseconds). * @return The chart that was created. */ - public static JFreeChart createTimeSeriesChart( + static JFreeChart createTimeSeriesChart( String title, String yAxisLabel, int seriesCount, Modified: java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/SystemStatistics.java ============================================================================= --- java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/SystemStatistics.java (original) +++ java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/SystemStatistics.java Mon Mar 16 14:42:56 2015 @@ -11,13 +11,20 @@ * Set the desired timer tick length in millis. * @param tickLengthMillis The desired tick length in millis. */ - void setTickLengthMillis(long tickLengthMillis); + void setNominalTickLengthMillis(long tickLengthMillis); /** - * Get the nominal length of one tick in millis. Actual ticks lengths may vary slightly. + * Get the nominal length of one tick in millis. + * Actual tick lengths lengths may vary slightly. * @return The nominal tick length in millis. */ - long getTickLengthMillis(); + long getNominalTickLengthMillis(); + + /** + * Get the end of the tick in Unix time (milliseconds since the epoch). + * @return The tick end in Unix time. + */ + long getTickEndTimeMillis(); /** * Start the timer thread for accumulating statistics. @@ -40,7 +47,7 @@ * Get the number of millis since the session started. * @return The number of millis since session start. */ - long getTotalElapsedMillis(); + long getElapsedMillis(); /** * Get the Unix start time of the session. @@ -105,6 +112,13 @@ * @return The data rate in [bytes/second]. */ public double getBytesPerSecond(); + + /** + * Get the immediate data rate which is the amount of data in megabytes received in the current tick + * over the time elapsed in the tick. + * @return The data rate in [bytes/second]. + */ + public double getMegabytesPerSecond(); /** * Get the number of milliseconds since the last tick. @@ -123,10 +137,10 @@ * @param ps The PrintStream for display. */ void printTick(PrintStream ps); - + /** - * Add subtask which will execute right before a new tick. - * @param subtask The subtask to execute. + * + * @param listener */ - //void addSubTask(TimerTask subtask); + void addSystemStatisticsListener(SystemStatisticsListener listener); } Modified: java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/SystemStatisticsImpl.java ============================================================================= --- java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/SystemStatisticsImpl.java (original) +++ java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/SystemStatisticsImpl.java Mon Mar 16 14:42:56 2015 @@ -2,6 +2,8 @@ import java.io.PrintStream; import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; import java.util.Timer; import java.util.TimerTask; @@ -12,21 +14,28 @@ */ public class SystemStatisticsImpl implements SystemStatistics { - long tickLengthMillis = 1000; // default is 1 second tick - long totalElapsedMillis; + long nominalTickLengthMillis = 1000; // default is 1 second tick + long tickStartTimeMillis; + long tickEndTimeMillis; + + long eventsInTick; + long bytesInTick; + + long elapsedMillis; long startTimeMillis; long stopTimeMillis; - long eventsSinceTick; - long bytesSinceTick; + long totalEvents; long totalBytes; - long tickStartMillis; + static final long Kb = 1 * 1024; static final long Mb = Kb * 1024; static final double milliToSecond = 0.001; static final DecimalFormat decimalFormat = new DecimalFormat("#.####"); Timer timer; + List<SystemStatisticsListener> listeners = new ArrayList<SystemStatisticsListener>(); + @Override public void update(int size) { addEvent(); @@ -35,18 +44,18 @@ } @Override - public void setTickLengthMillis(long tickLengthMillis) { - this.tickLengthMillis = tickLengthMillis; - } - - @Override - public long getTickLengthMillis() { - return tickLengthMillis; - } - - @Override - public long getTotalElapsedMillis() { - return totalElapsedMillis; + public void setNominalTickLengthMillis(long tickLengthMillis) { + this.nominalTickLengthMillis = tickLengthMillis; + } + + @Override + public long getNominalTickLengthMillis() { + return nominalTickLengthMillis; + } + + @Override + public long getElapsedMillis() { + return System.currentTimeMillis() - startTimeMillis; } @Override @@ -61,7 +70,12 @@ @Override public long getTickElapsedMillis() { - return System.currentTimeMillis() - tickStartMillis; + return System.currentTimeMillis() - tickStartTimeMillis; + } + + @Override + public long getTickEndTimeMillis() { + return tickEndTimeMillis; } /** @@ -70,7 +84,7 @@ @Override public long getEventsReceived() { - return eventsSinceTick; + return eventsInTick; } @Override @@ -80,8 +94,8 @@ @Override public double getEventsPerSecond() { - if (eventsSinceTick > 0 && getTickElapsedMillis() > 0) { - return (double) eventsSinceTick / millisToSeconds(getTickElapsedMillis()); + if (eventsInTick > 0 && getTickElapsedMillis() > 0) { + return (double) eventsInTick / millisToSeconds(getTickElapsedMillis()); } else { return 0.; } @@ -90,7 +104,7 @@ @Override public double getAverageEventsPerSecond() { try { - return Double.parseDouble(decimalFormat.format(totalEvents / millisToSeconds(getTotalElapsedMillis()))); + return Double.parseDouble(decimalFormat.format(totalEvents / millisToSeconds(getElapsedMillis()))); } catch (NumberFormatException e) { return 0; } @@ -102,7 +116,7 @@ @Override public long getBytesReceived() { - return bytesSinceTick; + return bytesInTick; } @Override @@ -113,7 +127,7 @@ @Override public double getAverageMegabytesPerSecond() { try { - return Double.parseDouble(decimalFormat.format(bytesToMb(totalBytes) / millisToSeconds(getTotalElapsedMillis()))); + return Double.parseDouble(decimalFormat.format(bytesToMb(totalBytes) / millisToSeconds(getElapsedMillis()))); } catch (NumberFormatException e) { return Double.NaN; } @@ -121,28 +135,59 @@ @Override public double getBytesPerSecond() { - if (bytesSinceTick > 0 && getTickElapsedMillis() > 0) - return (double) bytesSinceTick / millisToSeconds(getTickElapsedMillis()); + if (bytesInTick > 0 && getTickElapsedMillis() > 0) + return (double) bytesInTick / millisToSeconds(getTickElapsedMillis()); else return 0.; } - + + @Override + public double getMegabytesPerSecond() { + double bytes = getBytesPerSecond(); + if (bytes > 0) { + return bytesToMb(bytes); + } else { + return 0; + } + } + @Override public void start() { // Set session start time variables. long currentTimeMillis = System.currentTimeMillis(); startTimeMillis = currentTimeMillis; - tickStartMillis = currentTimeMillis; - + tickStartTimeMillis = currentTimeMillis; + + // Notify listeners of start. + for (SystemStatisticsListener listener : listeners) { + listener.started(this); + } + // Start timer task which executes at the nominal tick length to calculate statistics periodically. TimerTask task = new TimerTask() { public void run() { + + // End the current tick. + endTick(); + + // Start the new tick. nextTick(); } }; timer = new Timer(); - timer.schedule(task, 0, tickLengthMillis); + timer.schedule(task, 0, nominalTickLengthMillis); + } + + void endTick() { + + // Set absolute end time of current tick. + this.tickEndTimeMillis = System.currentTimeMillis(); + + // Activate listeners. + for (SystemStatisticsListener listener : listeners) { + listener.endTick(this); + } } @Override @@ -155,12 +200,21 @@ // Set stop time. stopTimeMillis = System.currentTimeMillis(); - } - + + // Notify listeners of stop. + for (SystemStatisticsListener listener : listeners) { + listener.stopped(this); + } + } + + public void addSystemStatisticsListener(SystemStatisticsListener listener) { + listeners.add(listener); + } + @Override public void printSession(PrintStream ps) { ps.println("session statistics ..."); - ps.println(" timeElapsedMillis = " + this.getTotalElapsedMillis()); + ps.println(" timeElapsedMillis = " + this.getElapsedMillis()); ps.println(" cumulativeEvents = " + this.getTotalEvents()); ps.println(" averageEventsPerSecond = " + this.getAverageEventsPerSecond()); ps.println(" averageMegaBytesPerSecond = " + this.getAverageMegabytesPerSecond()); @@ -176,37 +230,42 @@ } void addEvent() { - eventsSinceTick += 1; + eventsInTick += 1; totalEvents += 1; } void addData(int size) { - bytesSinceTick += size; + bytesInTick += size; totalBytes += size; } void updateElapsedTime() { - totalElapsedMillis = System.currentTimeMillis() - startTimeMillis; + elapsedMillis = System.currentTimeMillis() - startTimeMillis; } // Bytes to megabytes to 2 decimal places. static final double bytesToMb(long size) { return Double.parseDouble(decimalFormat.format((double) size / Mb)); } + + // Bytes to megabytes to 2 decimal places. + static final double bytesToMb(double size) { + return Double.parseDouble(decimalFormat.format(size / Mb)); + } static final double millisToSeconds(long millis) { return ((double) millis) / 1000.; } synchronized void nextTick() { - eventsSinceTick = 0; - bytesSinceTick = 0; - tickStartMillis = System.currentTimeMillis(); + eventsInTick = 0; + bytesInTick = 0; + tickStartTimeMillis = System.currentTimeMillis(); } public abstract class SystemStatisticsProvider implements ValueProvider { } - + public class AverageEventsPerSecondProvider extends SystemStatisticsProvider { @Override Modified: java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/et/EtSystemStripCharts.java ============================================================================= --- java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/et/EtSystemStripCharts.java (original) +++ java/trunk/monitoring-util/src/main/java/org/hps/monitoring/subsys/et/EtSystemStripCharts.java Mon Mar 16 14:42:56 2015 @@ -1,27 +1,53 @@ +/** + * + */ package org.hps.monitoring.subsys.et; import java.util.ArrayList; +import java.util.Date; import java.util.List; import org.hps.monitoring.plotting.MonitoringPlotFactory; -import org.hps.monitoring.plotting.StripChartUpdater; +import org.hps.monitoring.subsys.SystemStatistics; import org.hps.monitoring.subsys.SystemStatisticsImpl; +import org.hps.monitoring.subsys.SystemStatisticsListener; import org.hps.record.et.EtEventProcessor; +import org.jfree.chart.JFreeChart; import org.jfree.data.time.Second; +import org.jfree.data.time.TimeSeriesCollection; import org.jlab.coda.et.EtEvent; import org.lcsim.util.aida.AIDA; /** - * A basic set of strip charts for monitoring the ET system. + * This will show a series of strip charts from ET system performance statistics + * such as event and data rates. + * + * @author Jeremy McCormick <[log in to unmask]> */ -public final class EtSystemStripCharts extends EtEventProcessor { +public class EtSystemStripCharts extends EtEventProcessor implements SystemStatisticsListener { + // The system statistics. SystemStatisticsImpl stats = new SystemStatisticsImpl(); - MonitoringPlotFactory plotFactory = (MonitoringPlotFactory) AIDA.defaultInstance().analysisFactory().createPlotterFactory("ET System Monitoring"); - List<StripChartUpdater> updaters = new ArrayList<StripChartUpdater>(); - public EtSystemStripCharts() { - stats.setTickLengthMillis(1000); + // Plotting API. + MonitoringPlotFactory plotFactory = + (MonitoringPlotFactory) AIDA.defaultInstance().analysisFactory().createPlotterFactory("ET System Monitoring"); + + // List of charts. + List<JFreeChart> charts = new ArrayList<JFreeChart>(); + + // Range size in milliseconds. + static final double RANGE_SIZE = 200000; + + // Chart collection indices. + static final int DATA_RATE_COLLECTION_INDEX = 0; + static final int TOTAL_DATA_COLLECTION_INDEX = 1; + static final int EVENT_RATE_COLLECTION_INDEX = 2; + static final int TOTAL_EVENTS_COLLECTION_INDEX = 3; + + public EtSystemStripCharts() { + // Set 2 seconds between statistics updates. + stats.setNominalTickLengthMillis(1000); } /** @@ -29,57 +55,37 @@ */ @Override public void startJob() { - - // Create the ET system strip charts. - createStripCharts(); + + System.out.println("EtSystemStripChartsNew.startJob"); + + // Register this class as a listener to activate update at end of statistics clock tick. + stats.addSystemStatisticsListener(this); // Start systems statistics task. stats.start(); } /** - * + * Create the strip charts for plotting the basic ET system statistics. */ private void createStripCharts() { - updaters.add(plotFactory.createStripChart( - "Data Rate", - "MB / second", - 1, - new String[] { "Data" }, - 999, - new Second(), - stats.new MegabytesPerSecondProvider(), - 200000L)); + + System.out.println("EtSystemStripChartsNew.createStripCharts"); - updaters.add(plotFactory.createStripChart( - "Total Data", - "Megabytes", - 1, - new String[] { "Data" }, - 999, - new Second(), - stats.new TotalMegabytesProvider(), - 200000L)); + // Data rate in megabytes per second. + // TODO: Add to same chart the average MB / second. + charts.add(plotFactory.createTimeSeriesChart("Data Rate", "MB / second", 1, null, RANGE_SIZE)); + + // Total megabytes received. + charts.add(plotFactory.createTimeSeriesChart("Total Data", "Megabytes", 1, null, RANGE_SIZE)); - updaters.add(plotFactory.createStripChart( - "Event Rate", - "Events / s", - 1, - new String[] { "Data" }, - 999, - new Second(), - stats.new EventsPerSecondProvider(), - 200000L)); + // Event rate in hertz. + // TODO: Add to same chart the average event rate. + charts.add(plotFactory.createTimeSeriesChart("Event Rate", "Hz", 1, null, RANGE_SIZE)); - updaters.add(plotFactory.createStripChart( - "Total Events", - "Number of Events", - 1, - new String[] { "Data" }, - 999, - new Second(), - stats.new TotalEventsProvider(), - 200000L)); + // Total number of events received. + charts.add(plotFactory.createTimeSeriesChart("Total Events", "Number of Events", 1, null, RANGE_SIZE)); + } @Override @@ -88,13 +94,39 @@ } public void endJob() { - - // Stop the strip chart updaters. - for (StripChartUpdater updater : updaters) { - updater.stop(); - } - // Stop system statistics task. stats.stop(); } -} + + TimeSeriesCollection getTimeSeriesCollection(int chartIndex) { + return (TimeSeriesCollection) charts.get(chartIndex).getXYPlot().getDataset(); + } + + /** + * Hook for updating the charts at end of statistics clock tick. + * @param stats The statistics with the system information. + */ + @Override + public void endTick(SystemStatistics stats) { + + Date now = new Date(stats.getTickEndTimeMillis()); + + getTimeSeriesCollection(DATA_RATE_COLLECTION_INDEX).getSeries(0).addOrUpdate( + new Second(now), stats.getBytesPerSecond() / 1000000); + getTimeSeriesCollection(TOTAL_DATA_COLLECTION_INDEX).getSeries(0).addOrUpdate( + new Second(now), stats.getTotalMegabytes()); + getTimeSeriesCollection(EVENT_RATE_COLLECTION_INDEX).getSeries(0).addOrUpdate( + new Second(now), stats.getEventsPerSecond()); + getTimeSeriesCollection(TOTAL_EVENTS_COLLECTION_INDEX).getSeries(0).addOrUpdate( + new Second(now), stats.getTotalEvents()); + } + + @Override + public void started(SystemStatistics stats) { + createStripCharts(); + } + + @Override + public void stopped(SystemStatistics stats) { + } +}