Package org.perf4j

Source Code of org.perf4j.LogParser

/* Copyright (c) 2008-2009 HomeAway, Inc.
* All rights reserved.  http://www.perf4j.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.perf4j;

import org.perf4j.helpers.*;
import org.perf4j.chart.StatisticsChartGenerator;
import org.perf4j.chart.GoogleChartGenerator;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
* LogParser provides the main method for reading a log of StopWatch output and generating statistics and graphs
* from that output. Run "java -jar pathToPerf4jJar --help" for instructions.
*
* @author Alex Devine
*/
public class LogParser {
    /**
     * The input log that is being parsed.
     */
    private Reader inputLog;
    /**
     * The stream where the GroupedTimingStatistics data will be printed - if null, no statistics will be printed
     */
    private PrintStream statisticsOutput;
    /**
     * The stream where graphing output will be printed - if null, no graphing output will be printed. May be the
     * same stream as statisticsOutput.
     */
    private PrintStream graphingOutput;
    /**
     * The chart generator used to send the mean time graph to graphingOutput.
     */
    private StatisticsChartGenerator meanTimeChartGenerator;
    /**
     * The chart generator used to send the TPS graph to graphingOutput.
     */
    private StatisticsChartGenerator tpsChartGenerator;
    /**
     * The length of time, in milliseconds, of the timeslice of each GroupedTimingStatistics.
     */
    private long timeSlice;
    /**
     * Whether or not "rollup statistics" should be created for each GroupedTimingStatistics created.
     */
    private boolean createRollupStatistics;
    /**
     * The formatter to use to print statistics.
     */
    private GroupedTimingStatisticsFormatter statisticsFormatter;

    // --- Constructors ---
    /**
     * Default constructor reads input from standard in, writes statistics output to standard out, does not write
     * graph output, has a time slice window of 30 seconds, and does not create rollup statistics.
     */
    public LogParser() {
        this(new InputStreamReader(System.in),
             System.out,
             null /* no graph output */,
             30000L,
             false /* don't create rollup statistics */,
             new GroupedTimingStatisticsTextFormatter());
    }

    /**
     * Creates a new LogParser to parse log data from the input.
     *
     * @param inputLog               The log being parsed, which should contain {@link org.perf4j.StopWatch} log messages.
     * @param statisticsOutput       The stream where calculated statistics information should be written - if null,
     *                               statistics data is not written.
     * @param graphingOutput         The stream where graphing data should be written - if null, graphs are not written.
     * @param timeSlice              The length of time, in milliseconds, of the timeslice of each statistics data created.
     * @param createRollupStatistics Whether or not "rollup statistics" should be created for each timeslice of data.
     * @param statisticsFormatter    The formatter to use to print GroupedTimingStatistics
     */
    public LogParser(Reader inputLog, PrintStream statisticsOutput, PrintStream graphingOutput,
                     long timeSlice, boolean createRollupStatistics,
                     GroupedTimingStatisticsFormatter statisticsFormatter) {
        this.inputLog = inputLog;
        this.statisticsOutput = statisticsOutput;
        this.graphingOutput = graphingOutput;
        this.timeSlice = timeSlice;
        this.createRollupStatistics = createRollupStatistics;
        if (graphingOutput != null) {
            this.meanTimeChartGenerator = newMeanTimeChartGenerator();
            this.tpsChartGenerator = newTpsChartGenerator();
        }
        this.statisticsFormatter = statisticsFormatter;
    }

    // --- Instance Methods ---

    /**
     * Reads all the data from the inputLog, parses it, and writes the statistics data and graphing data as desired
     * to the output streams.
     */
    public void parseLog() {

        Iterator<StopWatch> stopWatchIter = new StopWatchLogIterator(inputLog);

        int i = 0;
        for (GroupingStatisticsIterator statsIter = new GroupingStatisticsIterator(stopWatchIter,
                                                                                   timeSlice,
                                                                                   createRollupStatistics);
             statsIter.hasNext();) {
            GroupedTimingStatistics statistics = statsIter.next();

            if (statisticsOutput != null) {
                statisticsOutput.print(statisticsFormatter.format(statistics));
            }

            if (graphingOutput != null) {
                meanTimeChartGenerator.appendData(statistics);
                tpsChartGenerator.appendData(statistics);
                if ((++i % StatisticsChartGenerator.DEFAULT_MAX_DATA_POINTS == 0) ||
                    (!statsIter.hasNext())) {
                    printGraphOutput();
                }
            }
        }
    }

    protected StatisticsChartGenerator newMeanTimeChartGenerator() {
        return new GoogleChartGenerator();
    }

    protected StatisticsChartGenerator newTpsChartGenerator() {
        return new GoogleChartGenerator(StatsValueRetriever.TPS_VALUE_RETRIEVER);
    }

    protected void printGraphOutput() {
        graphingOutput.println("<br/><br/><img src=\"" + meanTimeChartGenerator.getChartUrl() + "\"/>");
        graphingOutput.println("<br/><br/><img src=\"" + tpsChartGenerator.getChartUrl() + "\"/>");
    }
   
    // --- Main and Static Methods ---

    public static void main(String[] args) {
        System.exit(runMain(args));
    }

    public static int runMain(String[] args) {
        try {
            List<String> argsList = new ArrayList<String>(Arrays.asList(args));

            if (printUsage(argsList)) {
                return 0;
            }

            PrintStream statisticsOutput = openStatisticsOutput(argsList);
            PrintStream graphingOutput = openGraphingOutput(argsList);
            long timeSlice = getTimeSlice(argsList);
            boolean rollupStatistics = getRollupStatistics(argsList);
            GroupedTimingStatisticsFormatter formatter = getStatisticsFormatter(argsList);
            Reader input = openInput(argsList);

            if (!argsList.isEmpty()) {
                printUnknownArgs(argsList);
                return 1;
            }

            new LogParser(input, statisticsOutput, graphingOutput, timeSlice, rollupStatistics, formatter).parseLog();

            closeGraphingOutput(graphingOutput);
        } catch ( Exception e ) {
            e.printStackTrace();
            return 1;
        }
        return 0;
    }

    protected static boolean printUsage(List<String> argsList) {
        if (getIndexOfArg(argsList, false, "-h", "--help", "-?", "--usage") >= 0) {
            System.out.println("Usage: LogParser [-o|--out|--output outputFile] " +
                               "[-g|--graph graphingOutputFile] " +
                               "[-t|--timeslice timeslice] " +
                               "[-r] " +
                               "[-f|--format text|csv] " +
                               "[logInputFile]");
            System.out.println("Arguments:");
            System.out.println("  logInputFile - The log file to be parsed. If not specified, log data is read from stdin.");
            System.out.println("  -o|--out|--output outputFile - The file where generated statistics should be written." +
                               " If not specified, statistics are written to stdout.");
            System.out.println("  -g|--graph graphingOutputFile - The file where generated perf graphs should be written." +
                               " If not specified, no graphs are written.");
            System.out.println("  -t|--timeslice timeslice - The length of time (in ms) of each timeslice for which" +
                               " statistics should be generated. Defaults to 30000 ms.");
            System.out.println("  -r - Whether or not statistics rollups should be generated." +
                               " If not specified, rollups are not generated.");
            System.out.println("  -f|--format text|csv - The format for the statistics output, either plain text or CSV." +
                               " Defaults to text.");
            System.out.println("                         If format is csv, then the columns output are tag, start, stop, mean, min, max, stddev, and count.");
            System.out.println();
            System.out.println("Note that out, stdout, err and stderr can be used as aliases to the standard output" +
                               " streams when specifying output files.");
            return true;
        }

        return false;
    }

    protected static PrintStream openStatisticsOutput(List<String> argsList) throws IOException {
        int indexOfOut = getIndexOfArg(argsList, true, "-o", "--output", "--out");
        if (indexOfOut >= 0) {
            String fileName = argsList.remove(indexOfOut + 1);
            argsList.remove(indexOfOut);
            return openStream(fileName);
        } else {
            return System.out;
        }
    }

    protected static PrintStream openGraphingOutput(List<String> argsList) throws IOException {
        int indexOfOut = getIndexOfArg(argsList, true, "-g", "--graph");
        if (indexOfOut >= 0) {
            String fileName = argsList.remove(indexOfOut + 1);
            argsList.remove(indexOfOut);
            PrintStream retVal = openStream(fileName);
            retVal.println("<html>");
            retVal.println("<head><title>Perf4J Performance Graphs</title></head>");
            retVal.println("<body>");
            return retVal;
        } else {
            return null;
        }
    }

    protected static void closeGraphingOutput(PrintStream graphingOutput) throws IOException {
        if (graphingOutput != null) {
            graphingOutput.println("</body></html>");
            if (graphingOutput != System.out && graphingOutput != System.err) {
                graphingOutput.close();
            }
        }
    }

    protected static long getTimeSlice(List<String> argsList) {
        int indexOfOut = getIndexOfArg(argsList, true, "-t", "--timeslice");
        if (indexOfOut >= 0) {
            String timeslice = argsList.remove(indexOfOut + 1);
            argsList.remove(indexOfOut);
            return Long.parseLong(timeslice);
        } else {
            return 30000L;
        }
    }

    protected static boolean getRollupStatistics(List<String> argsList) {
        int indexOfOut = getIndexOfArg(argsList, false, "-r", "--rollup");
        if (indexOfOut >= 0) {
            argsList.remove(indexOfOut);
            return true;
        } else {
            return false;
        }
    }

    protected static GroupedTimingStatisticsFormatter getStatisticsFormatter(List<String> argsList) {
        int indexOfFormat = getIndexOfArg(argsList, true, "-f", "--format");
        if (indexOfFormat >= 0) {
            String formatString = argsList.remove(indexOfFormat + 1);
            argsList.remove(indexOfFormat);
            if ("text".equalsIgnoreCase(formatString)) {
                return new GroupedTimingStatisticsTextFormatter();
            } else if ("csv".equalsIgnoreCase(formatString)) {
                return new GroupedTimingStatisticsCsvFormatter();
            } else {
                throw new IllegalArgumentException("Unknown format type: " + formatString);
            }
        } else {
            return new GroupedTimingStatisticsTextFormatter();
        }
    }

    protected static Reader openInput(List<String> argsList) throws IOException {
        if (argsList.isEmpty()) {
            return new InputStreamReader(System.in);
        } else {
            String fileName = argsList.remove(0);
            return new BufferedReader(new FileReader(fileName));
        }
    }

    protected static void printUnknownArgs(List<String> argsList) {
        System.out.println("Unknown arguments: ");
        for (String arg : argsList) {
            System.out.print(arg + " ");
        }
        System.out.println();
    }

    protected static int getIndexOfArg(List<String> args, boolean needsParam, String... argNames) {
        int retVal = -1;
        boolean foundArg = false;
        for (String argName : argNames) {
            int argIndex = args.indexOf(argName);
            if (argIndex >= 0) {
                if (foundArg) {
                    throw new IllegalArgumentException("You must specify only one of " + Arrays.toString(argNames));
                }
                retVal = argIndex;
                foundArg = true;
            }
        }

        if ((retVal >= 0) && needsParam && (retVal == args.size() - 1)) {
            throw new IllegalArgumentException("You must specify a parameter for the " + args.get(retVal) + " arg");
        }

        return retVal;
    }

    protected static PrintStream openStream(String fileName) throws IOException {
        if ("stdout".equals(fileName) || "out".equals(fileName)) {
            return System.out;
        } else if ("stderr".equals(fileName) || "err".equals(fileName)) {
            return System.err;
        } else {
            return new PrintStream(new FileOutputStream(fileName), true);
        }
    }
}
TOP

Related Classes of org.perf4j.LogParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.