
org.perf4j.LogParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of perf4j Show documentation
Show all versions of perf4j Show documentation
Performance statistics logging and monitoring toolkit extension to log4j and the java.util.logging framework.
/* 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.GroupingStatisticsIterator;
import org.perf4j.helpers.StopWatchLogIterator;
import org.perf4j.helpers.StatsValueRetriever;
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 -cp pathToPerf4jJar org.per4j.LogParser --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;
// --- 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, 30000L, false);
}
/**
* 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.
*/
public LogParser(Reader inputLog, PrintStream statisticsOutput, PrintStream graphingOutput,
long timeSlice, boolean createRollupStatistics) {
this.inputLog = inputLog;
this.statisticsOutput = statisticsOutput;
this.graphingOutput = graphingOutput;
this.timeSlice = timeSlice;
this.createRollupStatistics = createRollupStatistics;
if (graphingOutput != null) {
this.meanTimeChartGenerator = newMeanTimeChartGenerator();
this.tpsChartGenerator = newTpsChartGenerator();
}
}
// --- 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 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.println(statistics.toString());
}
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("
");
graphingOutput.println("
");
}
// --- Main and Static Methods ---
public static void main(String[] args) {
System.exit(runMain(args));
}
public static int runMain(String[] args) {
try {
List argsList = new ArrayList(Arrays.asList(args));
if (printUsage(argsList)) {
return 0;
}
PrintStream statisticsOutput = openStatisticsOutput(argsList);
PrintStream graphingOutput = openGraphingOutput(argsList);
long timeSlice = getTimeSlice(argsList);
boolean rollupStatistics = getRollupStatistics(argsList);
Reader input = openInput(argsList);
if (!argsList.isEmpty()) {
printUnknownArgs(argsList);
return 1;
}
new LogParser(input, statisticsOutput, graphingOutput, timeSlice, rollupStatistics).parseLog();
closeGraphingOutput(graphingOutput);
} catch ( Exception e ) {
e.printStackTrace();
return 1;
}
return 0;
}
protected static boolean printUsage(List 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] [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();
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 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 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("");
retVal.println("<span class="hljs-string">Perf4J Performance Graphs</span> ");
retVal.println("");
return retVal;
} else {
return null;
}
}
protected static void closeGraphingOutput(PrintStream graphingOutput) throws IOException {
if (graphingOutput != null) {
graphingOutput.println("");
if (graphingOutput != System.out && graphingOutput != System.err) {
graphingOutput.close();
}
}
}
protected static long getTimeSlice(List 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 argsList) {
int indexOfOut = getIndexOfArg(argsList, false, "-r", "--rollup");
if (indexOfOut >= 0) {
argsList.remove(indexOfOut);
return true;
} else {
return false;
}
}
protected static Reader openInput(List 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 argsList) {
System.out.println("Unknown arguments: ");
for (String arg : argsList) {
System.out.print(arg + " ");
}
System.out.println();
}
protected static int getIndexOfArg(List 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);
}
}
}