|  | // Copyright 2014 The Bazel Authors. All rights reserved. | 
|  | // | 
|  | // 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 com.google.devtools.build.lib.profiler; | 
|  |  | 
|  | import static java.util.stream.Collectors.joining; | 
|  |  | 
|  | import com.google.common.collect.ImmutableList; | 
|  | import com.google.common.collect.Range; | 
|  | import java.text.DecimalFormat; | 
|  | import java.text.DecimalFormatSymbols; | 
|  | import java.util.Locale; | 
|  |  | 
|  | /** | 
|  | * Metric data for {@code description} object. Contains count, average, standard deviation, max and | 
|  | * histogram. | 
|  | */ | 
|  | public final class MetricData { | 
|  |  | 
|  | private final Object description; | 
|  | private final ImmutableList<HistogramElement> histogram; | 
|  | private final int count; | 
|  | private final double avg; | 
|  | private final double stdDev; | 
|  | private final int max; | 
|  | public MetricData(Object description, ImmutableList<HistogramElement> histogram, int count, | 
|  | double avg, double stdDev, int max) { | 
|  | this.description = description; | 
|  | this.histogram = histogram; | 
|  | this.count = count; | 
|  | this.avg = avg; | 
|  | this.stdDev = stdDev; | 
|  | this.max = max; | 
|  | } | 
|  |  | 
|  | public Object getDescription() { | 
|  | return description; | 
|  | } | 
|  |  | 
|  | public ImmutableList<HistogramElement> getHistogram() { | 
|  | return histogram; | 
|  | } | 
|  |  | 
|  | public int getCount() { | 
|  | return count; | 
|  | } | 
|  |  | 
|  | public double getAvg() { | 
|  | return avg; | 
|  | } | 
|  |  | 
|  | public double getStdDev() { | 
|  | return stdDev; | 
|  | } | 
|  |  | 
|  | public int getMax() { | 
|  | return max; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public String toString() { | 
|  | if (count == 0) { | 
|  | return "'" + description + "'. Zero data recorded"; | 
|  | } | 
|  | DecimalFormat fmt = new DecimalFormat("0.###", new DecimalFormatSymbols(Locale.US)); | 
|  | return "'" | 
|  | + description | 
|  | + "'. " | 
|  | + " Count: " | 
|  | + count | 
|  | + " Avg: " | 
|  | + fmt.format(avg) | 
|  | + " StdDev: " | 
|  | + fmt.format(stdDev) | 
|  | + " Max: " | 
|  | + max | 
|  | + " Histogram:\n  " | 
|  | + histogram | 
|  | .stream() | 
|  | .filter(element -> element.count > 0) | 
|  | .map(Object::toString) | 
|  | .collect(joining("\n  ")); | 
|  | } | 
|  |  | 
|  | /** An histogram element that contains the range that applies to and the number of elements. */ | 
|  | public static final class HistogramElement { | 
|  |  | 
|  | private final Range<Integer> range; | 
|  | private final int count; | 
|  |  | 
|  | HistogramElement(Range<Integer> range, int count) { | 
|  | this.range = range; | 
|  | this.count = count; | 
|  | } | 
|  |  | 
|  | public Range<Integer> getRange() { | 
|  | return range; | 
|  | } | 
|  |  | 
|  | public int getCount() { | 
|  | return count; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public String toString() { | 
|  |  | 
|  | return String.format("%-15s:%10s", | 
|  | "[" + range.lowerEndpoint() + ".." + (range.hasUpperBound() | 
|  | ? range.upperEndpoint() | 
|  | : "\u221e") // infinite symbol | 
|  | + " ms]", count); | 
|  | } | 
|  | } | 
|  | } |