package com.github.projectflink.common; import java.awt.BasicStroke; import java.awt.Dimension; import java.io.File; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jfree.chart.ChartColor; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.SeriesRenderingOrder; import org.jfree.chart.plot.ValueMarker; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.util.RelativeDateFormat; import org.jfree.data.time.Millisecond; import org.jfree.data.time.Minute; import org.jfree.data.time.MovingAverage; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; import org.jfree.data.xy.XYDataset; import org.jfree.ui.ApplicationFrame; import org.jfree.ui.RectangleInsets; import org.jfree.ui.RefineryUtilities; public class KafkaFT extends ApplicationFrame { private static final long serialVersionUID = 1L; public KafkaFT(String s, String generatorLogPath, String stateMachineLogPath) throws Exception { super(s); WhyOO res = createDataset(generatorLogPath, stateMachineLogPath); JFreeChart jfreechart = createChart(res.ds); // add kill events: for(Long killEventTime: res.killEventTime) { addKillEvent(jfreechart.getXYPlot(), killEventTime); } // add illegal state trans events: for(Long illegalEventTime: res.illegalStates) { addIllegalEvent(jfreechart.getXYPlot(), illegalEventTime); } ChartPanel chartpanel = new ChartPanel(jfreechart); chartpanel.setPreferredSize(new Dimension(1200, 600)); setContentPane(chartpanel); } private static void addKillEvent(XYPlot xyplot, long pos) { ValueMarker vm = new ValueMarker(pos); vm.setPaint(ChartColor.VERY_DARK_GREEN); vm.setLabelOffset(new RectangleInsets(10.0D, 1.0D, 1.0D, 1.0D)); vm.setLabel("Container Kill Event"); vm.setStroke(new BasicStroke(2)); xyplot.addDomainMarker(vm); } private static void addIllegalEvent(XYPlot xyplot, long pos) { ValueMarker vm = new ValueMarker(pos); vm.setPaint(ChartColor.LIGHT_YELLOW); vm.setLabelOffset(new RectangleInsets(10.0D, 1.0D, 1.0D, 1.0D)); vm.setLabel("Illegal State"); vm.setStroke(new BasicStroke(2)); xyplot.addDomainMarker(vm); } private static JFreeChart createChart(XYDataset xydataset) { JFreeChart jfreechart = ChartFactory.createTimeSeriesChart("Flink Exactly-Once on Kafka with YARN Chaos Monkey", "Date", "Value", xydataset, true, true, false); XYPlot xyplot = (XYPlot) jfreechart.getPlot(); XYLineAndShapeRenderer r0 = (XYLineAndShapeRenderer) xyplot.getRenderer(0); // draw data points as points r0.setSeriesShapesVisible(2, true); r0.setSeriesLinesVisible(2, true); // order elements as assed xyplot.setSeriesRenderingOrder(SeriesRenderingOrder.FORWARD); DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis(); Number first = xydataset.getX(0, 0); Minute minute = new Minute(new Date((Long)first)); System.out.println("first = "+first); RelativeDateFormat relativedateformat = new RelativeDateFormat(minute.getFirstMillisecond()); relativedateformat.setSecondFormatter(new DecimalFormat("00")); dateaxis.setDateFormatOverride(relativedateformat); //dateaxis.setDateFormatOverride(new SimpleDateFormat("mm:ss")); ValueAxis valueaxis = xyplot.getRangeAxis(); valueaxis.setAutoRangeMinimumSize(1.0D); valueaxis.setLabel("Elements/Core"); xyplot.getRenderer().setSeriesPaint(2, ChartColor.DARK_MAGENTA); return jfreechart; } public static class WhyOO { public XYDataset ds; public List<Long> killEventTime; public List<Long> illegalStates; } private static WhyOO createDataset(String generatorLogPath, String stateMachineLogPath) throws Exception { WhyOO res = new WhyOO(); res.killEventTime = new ArrayList<Long>(); res.illegalStates = new ArrayList<Long>(); TimeSeries generatorTimeseries = new TimeSeries("Data Generator"); { Scanner sc = new Scanner(new File(generatorLogPath)); String l; Pattern throughputPattern = Pattern.compile("([0-9:,]+) INFO.*generated.*That's ([0-9.]+) elements\\/second\\/core.*"); SimpleDateFormat dateParser = new SimpleDateFormat("HH:mm:ss,SSS"); while (sc.hasNextLine()) { l = sc.nextLine(); Matcher tpMatcher = throughputPattern.matcher(l); if (tpMatcher.matches()) { String time = tpMatcher.group(1); double eps = Double.valueOf(tpMatcher.group(2)); generatorTimeseries.addOrUpdate(new Millisecond(dateParser.parse(time)), eps); } } } TimeSeries consumerTimeseries = new TimeSeries("State Machine"); { Scanner sc = new Scanner(new File(stateMachineLogPath)); String l; Pattern throughputPattern = Pattern.compile("([0-9:,]+) INFO.*That's ([0-9.]+) elements\\/second\\/core.*"); Pattern failPattern = Pattern.compile("([0-9:,]+) ERROR .* failed.*"); Pattern illegalStatePattern = Pattern.compile("([0-9:,]+) INFO .*Detected invalid state transition ALERT.*"); SimpleDateFormat dateParser = new SimpleDateFormat("HH:mm:ss,SSS"); while (sc.hasNextLine()) { l = sc.nextLine(); Matcher tpMatcher = throughputPattern.matcher(l); if (tpMatcher.matches()) { String time = tpMatcher.group(1); double eps = Double.valueOf(tpMatcher.group(2)); consumerTimeseries.addOrUpdate(new Millisecond(dateParser.parse(time)), eps); } Matcher failMatcher = failPattern.matcher(l); if(failMatcher.matches()) { String time = failMatcher.group(1); res.killEventTime.add(dateParser.parse(time).getTime()); } Matcher illegalMatcher = illegalStatePattern.matcher(l); if(illegalMatcher.matches()) { String time = illegalMatcher.group(1); res.illegalStates.add(dateParser.parse(time).getTime()); } } } TimeSeriesCollection timeseriescollection = new TimeSeriesCollection(); // createPointMovingAverage(TimeSeries source, java.lang.String name, int pointCount) // timeseriescollection.addSeries(generatorTimeseries); timeseriescollection.addSeries(MovingAverage.createPointMovingAverage(generatorTimeseries, "Data Generator (Avg)", 50)); //timeseriescollection.addSeries(MovingAverage.createMovingAverage(generatorTimeseries, "whyName?", 20, 20)); // timeseriescollection.addSeries(consumerTimeseries); timeseriescollection.addSeries(MovingAverage.createMovingAverage(consumerTimeseries, "State Machine (Avg)", 1000,0)); System.out.println("Generator elements " + generatorTimeseries.getItemCount()); System.out.println("Consumer elements " + consumerTimeseries.getItemCount()); res.ds = timeseriescollection; return res; } /* public static JPanel createDemoPanel() { JFreeChart jfreechart = createChart(createDataset()); return new ChartPanel(jfreechart); } */ public static void main(String args[]) throws Exception { KafkaFT timeseriesdemo6 = new KafkaFT("Flink Exactly Once Processing", args[0], args[1]); timeseriesdemo6.pack(); RefineryUtilities.centerFrameOnScreen(timeseriesdemo6); timeseriesdemo6.setVisible(true); } }