/* 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.logback;
import org.perf4j.GroupedTimingStatistics;
import org.perf4j.helpers.GroupedTimingStatisticsCsvFormatter;
import org.perf4j.helpers.MiscUtils;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.LayoutBase;
/**
* A layout that outputs {@link org.perf4j.GroupedTimingStatistics} instances as comma-separated values. Thus, this
* layout is designed to be attached to appenders that are themselves attached to an
* {@link AsyncCoalescingStatisticsAppender}.
* <p>
* By default, each GroupedTimingStatistics object is output as a bunch of lines, with one line for each tagged
* {@link org.perf4j.TimingStatistics} instance contained within the GroupedTimingStatistics object. The following
* "columns" are output, separated by commas:
* <ol>
* <li>tag - the tag name of the code block that the statistics refer to
* <li>start - the start time of timing window
* <li>stop - the stop time of the timing window
* <li>mean - the mean execution time of stop watch logs that completed in the timing window
* <li>min - the min execution time of stop watch logs that completed in the timing window
* <li>max - the max execution time of stop watch logs that completed in the timing window
* <li>stddev - the standard deviation of the execution times of stop watch logs that completed in the timing window
* <li>count - the count of stop watch logs that completed during the timing window
* </ol>
* <p>
* You can modify the columns output using the <b>Columns</b> option. For example, you could specify the Columns option
* as "tag,start,stop,mean,count" to only output those specified values. In addition to the values specified above you
* can also use "tps" to output transactions per second.
* <p>
* In addition to the default output of one line per tag for each GroupedTimingStatistics object, this layout also
* supports a <b>Pivot</b> option which outputs just a single line for an entire GroupedTimingStatistics object. When
* pivot is true you should set the Columns to specify the values from the specific tags you want to output. For
* example, setting Pivot to true and setting Columns to "start,stop,codeBlock1Mean,codeBlock2Mean" would cause, for
* each GroupedTimingStatistics object, a single line to be output with the start and stop times of the window, the
* mean execution time for all stop watch logs with a codeBlock1 tag, and the mean execution time for all stop watch
* logs with a codeBlock2 tag.
*
* @author Alex Devine
* @author Xu Huisheng
*/
public class StatisticsCsvLayout extends LayoutBase<LoggingEvent> {
// --- configuration options ---
/**
* Pivot option
*/
private boolean pivot = false;
/**
* Columns option, a comma-separated list of column values to output.
*/
private String columns = GroupedTimingStatisticsCsvFormatter.DEFAULT_FORMAT_STRING;
/**
* PrintNotStatistics option
*/
private boolean printNonStatistics = false;
// --- contained objects ---
/**
* The csvFormatter is created in the {@link #start} method. The work of actually formatting the
* GroupedTimingStatistics object is delegated to this object.
*/
protected GroupedTimingStatisticsCsvFormatter csvFormatter;
// --- configuration options ---
/**
* The <b>Pivot</b> option, which is false by default, determines whether or not a single line will be output for
* each GroupedTimingStatistics object, or whether one line for each tag within a GroupedTimingStatistics object
* will be output.
*
* @return the Pivot option.
*/
public boolean isPivot() { return pivot; }
/**
* Sets the value of the <b>Pivot</b> option.
*
* @param pivot The new Pivot option value.
*/
public void setPivot(boolean pivot) { this.pivot = pivot; }
/**
* The <b>Columns</b> option is a comma-separated list of the values that should be output for each line that
* is printed. See the class javadoc for the allowed value.
*
* @return the Columns option.
*/
public String getColumns() { return columns; }
/**
* Sets the value of the <b>Columns</b> option.
*
* @param columns The new Columns option value.
*/
public void setColumns(String columns) { this.columns = columns; }
/**
* Gets the value of the <b>PrintNonStatistics</b> option. In general, this layout should only be used for
* appenders that deal with GroupedTimingStatistics objects (e.g. a FileAppender attached to an
* {@link AsyncCoalescingStatisticsAppender}). By default, any logging event where the message is NOT a
* GroupedTimingStatistics object is not output. However, if this option is set to true, then
* non-GroupedTimingStatistics messages will be output as their string value.
*
* @return the PrintNonStatistics option
*/
public boolean isPrintNonStatistics() { return printNonStatistics; }
/**
* Sets the value of the <b>PrintNonStatistics</b> option.
*
* @param printNonStatistics The new PrintNonStatistics option value.
*/
public void setPrintNonStatistics(boolean printNonStatistics) { this.printNonStatistics = printNonStatistics; }
public String doLayout(LoggingEvent event) {
try {
//we assume that the event is a GroupedTimingStatistics object
return csvFormatter.format((GroupedTimingStatistics) event.getArgumentArray()[0]);
} catch (ClassCastException cce) {
//then it's not a GroupedTimingStatistics object
if (isPrintNonStatistics()) {
return MiscUtils.escapeStringForCsv(event.getFormattedMessage(), new StringBuilder())
.append(MiscUtils.NEWLINE).toString();
} else {
return "";
}
}
}
@Override
public void start() {
super.start();
csvFormatter = new GroupedTimingStatisticsCsvFormatter(isPivot(), getColumns());
}
}