1 // Copyright 2014 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base.metrics; 6 7 import android.text.format.DateUtils; 8 9 import java.util.List; 10 11 /** 12 * Java API for recording UMA histograms. 13 * */ 14 public class RecordHistogram { 15 /** 16 * Records a sample in a boolean UMA histogram of the given name. Boolean histogram has two 17 * buckets, corresponding to success (true) and failure (false). This is the Java equivalent of 18 * the UMA_HISTOGRAM_BOOLEAN C++ macro. 19 * 20 * @param name name of the histogram 21 * @param sample sample to be recorded, either true or false 22 */ recordBooleanHistogram(String name, boolean sample)23 public static void recordBooleanHistogram(String name, boolean sample) { 24 UmaRecorderHolder.get().recordBooleanHistogram(name, sample); 25 } 26 27 /** 28 * Records a sample in an enumerated histogram of the given name and boundary. Note that 29 * {@code max} identifies the histogram - it should be the same at every invocation. This is the 30 * Java equivalent of the UMA_HISTOGRAM_ENUMERATION C++ macro. 31 * 32 * @param name name of the histogram 33 * @param sample sample to be recorded, at least 0 and at most {@code max-1} 34 * @param max upper bound for legal sample values - all sample values have to be strictly 35 * lower than {@code max} 36 */ recordEnumeratedHistogram(String name, int sample, int max)37 public static void recordEnumeratedHistogram(String name, int sample, int max) { 38 recordExactLinearHistogram(name, sample, max); 39 } 40 41 /** 42 * Records a sample in a count histogram. This is the Java equivalent of the 43 * UMA_HISTOGRAM_COUNTS_1M C++ macro. 44 * 45 * @param name name of the histogram 46 * @param sample sample to be recorded, at least 1 and at most 999999 47 */ recordCount1MHistogram(String name, int sample)48 public static void recordCount1MHistogram(String name, int sample) { 49 UmaRecorderHolder.get().recordExponentialHistogram(name, sample, 1, 1_000_000, 50); 50 } 51 52 /** 53 * Records a sample in a count histogram. This is the Java equivalent of the 54 * UMA_HISTOGRAM_COUNTS_100 C++ macro. 55 * 56 * @param name name of the histogram 57 * @param sample sample to be recorded, at least 1 and at most 99 58 */ recordCount100Histogram(String name, int sample)59 public static void recordCount100Histogram(String name, int sample) { 60 UmaRecorderHolder.get().recordExponentialHistogram(name, sample, 1, 100, 50); 61 } 62 63 /** 64 * Records a sample in a count histogram. This is the Java equivalent of the 65 * UMA_HISTOGRAM_COUNTS_1000 C++ macro. 66 * 67 * @param name name of the histogram 68 * @param sample sample to be recorded, at least 1 and at most 999 69 */ recordCount1000Histogram(String name, int sample)70 public static void recordCount1000Histogram(String name, int sample) { 71 UmaRecorderHolder.get().recordExponentialHistogram(name, sample, 1, 1_000, 50); 72 } 73 74 /** 75 * Records a sample in a count histogram. This is the Java equivalent of the 76 * UMA_HISTOGRAM_COUNTS_100000 C++ macro. 77 * 78 * @param name name of the histogram 79 * @param sample sample to be recorded, at least 1 and at most 99999 80 */ recordCount100000Histogram(String name, int sample)81 public static void recordCount100000Histogram(String name, int sample) { 82 UmaRecorderHolder.get().recordExponentialHistogram(name, sample, 1, 100_000, 50); 83 } 84 85 /** 86 * Records a sample in a count histogram. This is the Java equivalent of the 87 * UMA_HISTOGRAM_CUSTOM_COUNTS C++ macro. 88 * 89 * @param name name of the histogram 90 * @param sample sample to be recorded, expected to fall in range {@code [min, max)} 91 * @param min the smallest expected sample value; at least 1 92 * @param max the smallest sample value that will be recorded in overflow bucket 93 * @param numBuckets the number of buckets including underflow ({@code [0, min)}) and overflow 94 * ({@code [max, inf)}) buckets; at most 100 95 */ recordCustomCountHistogram( String name, int sample, int min, int max, int numBuckets)96 public static void recordCustomCountHistogram( 97 String name, int sample, int min, int max, int numBuckets) { 98 UmaRecorderHolder.get().recordExponentialHistogram(name, sample, min, max, numBuckets); 99 } 100 101 /** 102 * Records a sample in a linear histogram. This is the Java equivalent for using 103 * {@code base::LinearHistogram}. 104 * 105 * @param name name of the histogram 106 * @param sample sample to be recorded, expected to fall in range {@code [min, max)} 107 * @param min the smallest expected sample value; at least 1 108 * @param max the smallest sample value that will be recorded in overflow bucket 109 * @param numBuckets the number of buckets including underflow ({@code [0, min)}) and overflow 110 * ({@code [max, inf)}) buckets; at most 100 111 */ recordLinearCountHistogram( String name, int sample, int min, int max, int numBuckets)112 public static void recordLinearCountHistogram( 113 String name, int sample, int min, int max, int numBuckets) { 114 UmaRecorderHolder.get().recordLinearHistogram(name, sample, min, max, numBuckets); 115 } 116 117 /** 118 * Records a sample in a percentage histogram. This is the Java equivalent of the 119 * UMA_HISTOGRAM_PERCENTAGE C++ macro. 120 * 121 * @param name name of the histogram 122 * @param sample sample to be recorded, at least 0 and at most 100 123 */ recordPercentageHistogram(String name, int sample)124 public static void recordPercentageHistogram(String name, int sample) { 125 recordExactLinearHistogram(name, sample, 101); 126 } 127 128 /** 129 * Records a sparse histogram. This is the Java equivalent of {@code base::UmaHistogramSparse}. 130 * 131 * @param name name of the histogram 132 * @param sample sample to be recorded: All values of {@code sample} are valid, including 133 * negative values. Keep the number of distinct values across all users 134 * {@code <= 100} ideally, definitely {@code <= 1000}. 135 */ recordSparseHistogram(String name, int sample)136 public static void recordSparseHistogram(String name, int sample) { 137 UmaRecorderHolder.get().recordSparseHistogram(name, sample); 138 } 139 140 /** 141 * Records a sample in a histogram of times. Useful for recording short durations. This is the 142 * Java equivalent of the UMA_HISTOGRAM_TIMES C++ macro. 143 * <p> 144 * Note that histogram samples will always be converted to milliseconds when logged. 145 * 146 * @param name name of the histogram 147 * @param durationMs duration to be recorded in milliseconds 148 */ recordTimesHistogram(String name, long durationMs)149 public static void recordTimesHistogram(String name, long durationMs) { 150 recordCustomTimesHistogramMilliseconds( 151 name, durationMs, 1, DateUtils.SECOND_IN_MILLIS * 10, 50); 152 } 153 154 /** 155 * Records a sample in a histogram of times. Useful for recording medium durations. This is the 156 * Java equivalent of the UMA_HISTOGRAM_MEDIUM_TIMES C++ macro. 157 * <p> 158 * Note that histogram samples will always be converted to milliseconds when logged. 159 * 160 * @param name name of the histogram 161 * @param durationMs duration to be recorded in milliseconds 162 */ recordMediumTimesHistogram(String name, long durationMs)163 public static void recordMediumTimesHistogram(String name, long durationMs) { 164 recordCustomTimesHistogramMilliseconds( 165 name, durationMs, 10, DateUtils.MINUTE_IN_MILLIS * 3, 50); 166 } 167 168 /** 169 * Records a sample in a histogram of times. Useful for recording long durations. This is the 170 * Java equivalent of the UMA_HISTOGRAM_LONG_TIMES C++ macro. 171 * <p> 172 * Note that histogram samples will always be converted to milliseconds when logged. 173 * 174 * @param name name of the histogram 175 * @param durationMs duration to be recorded in milliseconds 176 */ recordLongTimesHistogram(String name, long durationMs)177 public static void recordLongTimesHistogram(String name, long durationMs) { 178 recordCustomTimesHistogramMilliseconds(name, durationMs, 1, DateUtils.HOUR_IN_MILLIS, 50); 179 } 180 181 /** 182 * Records a sample in a histogram of times. Useful for recording long durations. This is the 183 * Java equivalent of the UMA_HISTOGRAM_LONG_TIMES_100 C++ macro. 184 * <p> 185 * Note that histogram samples will always be converted to milliseconds when logged. 186 * 187 * @param name name of the histogram 188 * @param durationMs duration to be recorded in milliseconds 189 */ recordLongTimesHistogram100(String name, long durationMs)190 public static void recordLongTimesHistogram100(String name, long durationMs) { 191 recordCustomTimesHistogramMilliseconds(name, durationMs, 1, DateUtils.HOUR_IN_MILLIS, 100); 192 } 193 194 /** 195 * Records a sample in a histogram of times with custom buckets. This is the Java equivalent of 196 * the UMA_HISTOGRAM_CUSTOM_TIMES C++ macro. 197 * <p> 198 * Note that histogram samples will always be converted to milliseconds when logged. 199 * 200 * @param name name of the histogram 201 * @param durationMs duration to be recorded in milliseconds; expected to fall in range 202 * {@code [min, max)} 203 * @param min the smallest expected sample value; at least 1 204 * @param max the smallest sample value that will be recorded in overflow bucket 205 * @param numBuckets the number of buckets including underflow ({@code [0, min)}) and overflow 206 * ({@code [max, inf)}) buckets; at most 100 207 */ recordCustomTimesHistogram( String name, long durationMs, long min, long max, int numBuckets)208 public static void recordCustomTimesHistogram( 209 String name, long durationMs, long min, long max, int numBuckets) { 210 recordCustomTimesHistogramMilliseconds(name, durationMs, min, max, numBuckets); 211 } 212 213 /** 214 * Records a sample in a histogram of sizes in KB. This is the Java equivalent of the 215 * UMA_HISTOGRAM_MEMORY_KB C++ macro. 216 * <p> 217 * Good for sizes up to about 500MB. 218 * 219 * @param name name of the histogram 220 * @param sizeInkB Sample to record in KB 221 */ recordMemoryKBHistogram(String name, int sizeInKB)222 public static void recordMemoryKBHistogram(String name, int sizeInKB) { 223 UmaRecorderHolder.get().recordExponentialHistogram(name, sizeInKB, 1000, 500000, 50); 224 } 225 226 /** 227 * Records a sample in a histogram of sizes in MB. This is the Java equivalent of the 228 * UMA_HISTOGRAM_MEMORY_MEDIUM_MB C++ macro. 229 * <p> 230 * Good for sizes up to about 4000MB. 231 * 232 * @param name name of the histogram 233 * @param sizeInMB Sample to record in MB 234 */ recordMemoryMediumMBHistogram(String name, int sizeInMB)235 public static void recordMemoryMediumMBHistogram(String name, int sizeInMB) { 236 UmaRecorderHolder.get().recordExponentialHistogram(name, sizeInMB, 1, 4000, 100); 237 } 238 239 /** 240 * Records a sample in a linear histogram where each bucket in range {@code [0, max)} counts 241 * exactly a single value. 242 * 243 * @param name name of the histogram 244 * @param sample sample to be recorded, expected to fall in range {@code [0, max)} 245 * @param max the smallest value counted in the overflow bucket, shouldn't be larger than 100 246 */ recordExactLinearHistogram(String name, int sample, int max)247 public static void recordExactLinearHistogram(String name, int sample, int max) { 248 // Range [0, 1) is counted in the underflow bucket. The first "real" bucket starts at 1. 249 final int min = 1; 250 // One extra is added for the overflow bucket. 251 final int numBuckets = max + 1; 252 UmaRecorderHolder.get().recordLinearHistogram(name, sample, min, max, numBuckets); 253 } 254 clampToInt(long value)255 private static int clampToInt(long value) { 256 if (value > Integer.MAX_VALUE) return Integer.MAX_VALUE; 257 // Note: Clamping to MIN_VALUE rather than 0, to let base/ histograms code do its own 258 // handling of negative values in the future. 259 if (value < Integer.MIN_VALUE) return Integer.MIN_VALUE; 260 return (int) value; 261 } 262 recordCustomTimesHistogramMilliseconds( String name, long duration, long min, long max, int numBuckets)263 private static void recordCustomTimesHistogramMilliseconds( 264 String name, long duration, long min, long max, int numBuckets) { 265 UmaRecorderHolder.get() 266 .recordExponentialHistogram( 267 name, clampToInt(duration), clampToInt(min), clampToInt(max), numBuckets); 268 } 269 270 /** 271 * Returns the number of samples recorded in the given bucket of the given histogram. 272 * 273 * @deprecated Raw counts are easy to misuse. Does not reset between batched tests. Use 274 * {@link org.chromium.base.test.util.HistogramWatcher} instead. 275 * 276 * @param name name of the histogram to look up 277 * @param sample the bucket containing this sample value will be looked up 278 */ 279 @Deprecated getHistogramValueCountForTesting(String name, int sample)280 public static int getHistogramValueCountForTesting(String name, int sample) { 281 return UmaRecorderHolder.get().getHistogramValueCountForTesting(name, sample); 282 } 283 284 /** 285 * Returns the number of samples recorded for the given histogram. 286 * 287 * @deprecated Raw counts are easy to misuse. Does not reset between batched tests. Use 288 * {@link org.chromium.base.test.util.HistogramWatcher} instead. 289 * 290 * @param name name of the histogram to look up 291 */ 292 @Deprecated getHistogramTotalCountForTesting(String name)293 public static int getHistogramTotalCountForTesting(String name) { 294 return UmaRecorderHolder.get().getHistogramTotalCountForTesting(name); 295 } 296 297 /** 298 * Returns the buckets of samples recorded for the given histogram. 299 * 300 * Use {@link org.chromium.base.test.util.HistogramWatcher} instead of using this directly. 301 * 302 * @param name name of the histogram to look up 303 */ getHistogramSamplesForTesting(String name)304 public static List<HistogramBucket> getHistogramSamplesForTesting(String name) { 305 return UmaRecorderHolder.get().getHistogramSamplesForTesting(name); 306 } 307 } 308