blob: 1f9abdeca1ff0c2eac9959aedf6ea551d86ec237 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.hadoop.fs.slive;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Class which provides a report for the given operation output
*/
class ReportWriter {
// simple measurement types
// expect long values
// these will be reported on + rates by this reporter
static final String OK_TIME_TAKEN = "milliseconds_taken";
static final String FAILURES = "failures";
static final String SUCCESSES = "successes";
static final String BYTES_WRITTEN = "bytes_written";
static final String FILES_CREATED = "files_created";
static final String DIR_ENTRIES = "dir_entries";
static final String OP_COUNT = "op_count";
static final String CHUNKS_VERIFIED = "chunks_verified";
static final String CHUNKS_UNVERIFIED = "chunks_unverified";
static final String BYTES_READ = "bytes_read";
static final String NOT_FOUND = "files_not_found";
static final String BAD_FILES = "bad_files";
private static final Log LOG = LogFactory.getLog(ReportWriter.class);
private static final String SECTION_DELIM = "-------------";
/**
* @return String to be used for as a section delimiter
*/
private String getSectionDelimiter() {
return SECTION_DELIM;
}
/**
* Writes a message the the logging library and the given print writer (if it
* is not null)
*
* @param msg
* the message to write
* @param os
* the print writer if specified to also write to
*/
private void writeMessage(String msg, PrintWriter os) {
LOG.info(msg);
if (os != null) {
os.println(msg);
}
}
/**
* Provides a simple report showing only the input size, and for each
* operation the operation type, measurement type and its values.
*
* @param input
* the list of operations to report on
* @param os
* any print writer for which output should be written to (along with
* the logging library)
*/
void basicReport(List<OperationOutput> input, PrintWriter os) {
writeMessage("Default report for " + input.size() + " operations ", os);
writeMessage(getSectionDelimiter(), os);
for (OperationOutput data : input) {
writeMessage("Operation \"" + data.getOperationType() + "\" measuring \""
+ data.getMeasurementType() + "\" = " + data.getValue(), os);
}
writeMessage(getSectionDelimiter(), os);
}
/**
* Provides a more detailed report for a given operation. This will output the
* keys and values for all input and then sort based on measurement type and
* attempt to show rates for various metrics which have expected types to be
* able to measure there rate. Currently this will show rates for bytes
* written, success count, files created, directory entries, op count and
* bytes read if the variable for time taken is available for each measurement
* type.
*
* @param operation
* the operation that is being reported on.
* @param input
* the set of data for that that operation.
* @param os
* any print writer for which output should be written to (along with
* the logging library)
*/
void opReport(String operation, List<OperationOutput> input,
PrintWriter os) {
writeMessage("Basic report for operation type " + operation, os);
writeMessage(getSectionDelimiter(), os);
for (OperationOutput data : input) {
writeMessage("Measurement \"" + data.getMeasurementType() + "\" = "
+ data.getValue(), os);
}
// split up into measurement types for rates...
Map<String, OperationOutput> combined = new TreeMap<String, OperationOutput>();
for (OperationOutput data : input) {
if (combined.containsKey(data.getMeasurementType())) {
OperationOutput curr = combined.get(data.getMeasurementType());
combined.put(data.getMeasurementType(), OperationOutput.merge(curr,
data));
} else {
combined.put(data.getMeasurementType(), data);
}
}
// handle the known types
OperationOutput timeTaken = combined.get(OK_TIME_TAKEN);
if (timeTaken != null) {
Long mTaken = Long.parseLong(timeTaken.getValue().toString());
if (mTaken > 0) {
NumberFormat formatter = Formatter.getDecimalFormatter();
for (String measurementType : combined.keySet()) {
Double rate = null;
String rateType = "";
if (measurementType.equals(BYTES_WRITTEN)) {
Long mbWritten = Long.parseLong(combined.get(measurementType)
.getValue().toString())
/ (Constants.MEGABYTES);
rate = (double) mbWritten / (double) (mTaken / 1000.0d);
rateType = "MB/sec";
} else if (measurementType.equals(SUCCESSES)) {
Long succ = Long.parseLong(combined.get(measurementType).getValue()
.toString());
rate = (double) succ / (double) (mTaken / 1000.0d);
rateType = "successes/sec";
} else if (measurementType.equals(FILES_CREATED)) {
Long filesCreated = Long.parseLong(combined.get(measurementType)
.getValue().toString());
rate = (double) filesCreated / (double) (mTaken / 1000.0d);
rateType = "files created/sec";
} else if (measurementType.equals(DIR_ENTRIES)) {
Long entries = Long.parseLong(combined.get(measurementType)
.getValue().toString());
rate = (double) entries / (double) (mTaken / 1000.0d);
rateType = "directory entries/sec";
} else if (measurementType.equals(OP_COUNT)) {
Long opCount = Long.parseLong(combined.get(measurementType)
.getValue().toString());
rate = (double) opCount / (double) (mTaken / 1000.0d);
rateType = "operations/sec";
} else if (measurementType.equals(BYTES_READ)) {
Long mbRead = Long.parseLong(combined.get(measurementType)
.getValue().toString())
/ (Constants.MEGABYTES);
rate = (double) mbRead / (double) (mTaken / 1000.0d);
rateType = "MB/sec";
}
if (rate != null) {
writeMessage("Rate for measurement \"" + measurementType + "\" = "
+ formatter.format(rate) + " " + rateType, os);
}
}
}
}
writeMessage(getSectionDelimiter(), os);
}
}