| /** |
| * 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); |
| } |
| |
| } |