blob: ec4f555aad56c239700839afee22daa18fb105da [file] [log] [blame] [view]
mpearson2b5f7e02016-10-03 21:27:031# Histogram Guidelines
2
3This document gives the best practices on how to use histograms in code and how
Caitlin Fischerb5e94352020-10-27 17:34:504to document the histograms for the dashboards. There are three general types
Darwin Huang1ca97ac2020-06-17 18:09:205of histograms: [enumerated histograms](#Enum-Histograms),
6[count histograms](#Count-Histograms) (for arbitrary numbers), and
7[sparse histograms](#When-To-Use-Sparse-Histograms) (for anything when the
8precision is important over a wide range and/or the range is not possible to
9specify a priori).
mpearson2b5f7e02016-10-03 21:27:0310
11[TOC]
12
Ilya Shermanb9641892020-11-06 00:53:5513## Defining Useful Metrics
Mark Pearsonb1d608d2018-06-05 19:59:4414
Ilya Shermanb9641892020-11-06 00:53:5515### Directly Measure What You Want
16
17Measure exactly what you want, whether that's the time used for a function call,
18the number of bytes transmitted to fetch a page, the number of items in a list,
19etc. Do not assume you can calculate what you want from other histograms, as
20most ways of doing this are incorrect.
21
22For example, suppose you want to measure the runtime of a function that just
23calls two subfunctions, each of which is instrumented with histogram logging.
24You might assume that you can simply sum the histograms for those two functions
25to get the total time, but that results in misleading data. If we knew which
26emissions came from which calls, we could pair them up and derive the total time
27for the function. However, histograms are pre-aggregated client-side, which
28means that there's no way to recover which emissions should be paired up. If you
29simply add up the two histograms to get a total duration histogram, you're
30implicitly assuming the two histograms' values are independent, which may not be
31the case.
32
33Directly measure what you care about; don't try to derive it from other data.
34
35### Provide Context
36
37When defining a new metric, think ahead about how you will analyze the
38data. Often, this will require providing context in order for the data to be
39interpretable.
40
41For enumerated histograms in particular, that often means including a bucket
42that can be used as a baseline for understanding the data recorded to other
43buckets: see the [enumerated histogram section](#Enum-Histograms).
44
45### Naming Your Histogram
46
47Histograms are taxonomized into categories, using dot (`.`) characters as
48separators. Thus, histogram names should be in the form Category.Name or
49Category.Subcategory.Name, etc., where each category organizes related
50histograms.
51
52It should be quite rare to introduce new top-level categories into the existing
53taxonomy. If you're tempted to do so, please look through the existing
Robert Kaplowcbc6fd62021-03-19 15:11:4054categories to see whether any matches the metric(s) that you are adding. To
55create a new category, the CL must be reviewed by
56[email protected].
Mark Pearsonb1d608d2018-06-05 19:59:4457
Mark Pearson4bd7ca892024-12-11 23:35:0858## Permitted Metrics
59
60Google has policies restricting what data can be collected and for what purpose.
61Googlers, see go/uma-privacy#principles to verify your desired histogram
62adheres to those policies.
63
Mark Pearson4c4bc972018-05-16 20:01:0664## Coding (Emitting to Histograms)
65
Daniel Cheng01cd75932020-02-06 16:43:4566Prefer the helper functions defined in
Mark Pearsoned73f1f2019-03-22 18:00:1267[histogram_functions.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_functions.h).
Daniel Cheng01cd75932020-02-06 16:43:4568These functions take a lock and perform a map lookup, but the overhead is
69generally insignificant. However, when recording metrics on the critical path
70(e.g. called in a loop or logged multiple times per second), use the macros in
71[histogram_macros.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h)
72instead. These macros cache a pointer to the histogram object for efficiency,
73though this comes at the cost of increased binary size: 130 bytes/macro usage
74sounds small but quickly adds up.
Mark Pearson159c38972018-06-05 19:44:0875
Mark Pearson4c4bc972018-05-16 20:01:0676### Don't Use the Same Histogram Logging Call in Multiple Places
77
78These logging macros and functions have long names and sometimes include extra
Caitlin Fischerb5e94352020-10-27 17:34:5079parameters (defining the number of buckets for example). Use a helper function
80if possible. This leads to shorter, more readable code that's also more
81resilient to problems that could be introduced when making changes. (One could,
Mark Pearson4c4bc972018-05-16 20:01:0682for example, erroneously change the bucketing of the histogram in one call but
83not the other.)
84
85### Use Fixed Strings When Using Histogram Macros
86
87When using histogram macros (calls such as `UMA_HISTOGRAM_ENUMERATION`), you're
Victor-Gabriel Savub2afb6f42019-10-23 07:28:2388not allowed to construct your string dynamically so that it can vary at a
Caitlin Fischerb5e94352020-10-27 17:34:5089callsite. At a given callsite (preferably you have only one), the string
90should be the same every time the macro is called. If you need to use dynamic
Mark Pearson74c53212019-03-08 00:34:0891names, use the functions in histogram_functions.h instead of the macros.
Mark Pearson4c4bc972018-05-16 20:01:0692
Arthur Milchiora70d5e62022-08-02 05:10:5693### Don't Use Same Inline String in Multiple Places
Mark Pearson4c4bc972018-05-16 20:01:0694
95If you must use the histogram name in multiple places, use a compile-time
96constant of appropriate scope that can be referenced everywhere. Using inline
97strings in multiple places can lead to errors if you ever need to revise the
Jana Grill81103722023-01-19 16:31:5398name and you update one location and forget another.
Mark Pearson4c4bc972018-05-16 20:01:0699
100### Efficiency
101
Mark Pearsoned73f1f2019-03-22 18:00:12102Generally, don't be concerned about the processing cost of emitting to a
103histogram (unless you're using [sparse
104histograms](#When-To-Use-Sparse-Histograms)). The normal histogram code is
105highly optimized. If you are recording to a histogram in particularly
106performance-sensitive or "hot" code, make sure you're using the histogram
107macros; see [reasons above](#Coding-Emitting-to-Histograms).
Mark Pearson4c4bc972018-05-16 20:01:06108
109## Picking Your Histogram Type
mpearson2b5f7e02016-10-03 21:27:03110
mpearson2b5f7e02016-10-03 21:27:03111### Enum Histograms
112
113Enumerated histogram are most appropriate when you have a list of connected /
Caitlin Fischerb5e94352020-10-27 17:34:50114related states that should be analyzed jointly. For example, the set of actions
115that can be done on the New Tab Page (use the omnibox, click a most visited
116tile, click a bookmark, etc.) would make a good enumerated histogram.
mpearson2b5f7e02016-10-03 21:27:03117If the total count of your histogram (i.e. the sum across all buckets) is
Caitlin Fischerb5e94352020-10-27 17:34:50118something meaningful—as it is in this example—that is generally a good sign.
mpearson2b5f7e02016-10-03 21:27:03119However, the total count does not have to be meaningful for an enum histogram
120to still be the right choice.
121
Caitlin Fischerb5e94352020-10-27 17:34:50122Enumerated histograms are also appropriate for counting events. Use a simple
Ilya Shermanb9641892020-11-06 00:53:55123boolean histogram. It's usually best if you have a comparison point in the same
Caitlin Fischerb5e94352020-10-27 17:34:50124histogram. For example, if you want to count pages opened from the history page,
125it might be a useful comparison to have the same histogram record the number of
126times the history page was opened.
Mark Pearsona768d0222019-03-20 02:16:00127
Ilya Shermanb9641892020-11-06 00:53:55128In rarer cases, it's okay if you only log to one bucket (say, `true`). However,
129think about whether this will provide enough [context](#Provide-Context). For
130example, suppose we want to understand how often users interact with a button.
Jared Saul73a9daaf2021-05-04 15:33:02131Just knowing that users clicked this particular button 1 million times in a day
Ilya Shermanb9641892020-11-06 00:53:55132is not very informative on its own: The size of Chrome's user base is constantly
133changing, only a subset of users have consented to metrics reporting, different
134platforms have different sampling rates for metrics reporting, and so on. The
135data would be much easier to make sense of if it included a baseline: how often
136is the button shown?
137
Mark Pearson07356b042024-05-16 20:06:08138There is another problem with using another histogram as a comparison point.
Giovanni Pezzino42bf19ed2024-06-18 12:59:44139Google systems for processing UMA data attempt to exclude data that is
Mark Pearson07356b042024-05-16 20:06:08140deemed unreliable or somehow anomalous. It's possible that it may exclude data
141from a client for one histogram and not exclude data from that client for the
142other.
143
Caitlin Fischerb5e94352020-10-27 17:34:50144If only a few buckets are emitted to, consider using a [sparse
Mark Pearson4d0b4632017-10-04 21:58:48145histogram](#When-To-Use-Sparse-Histograms).
146
Daniel Cheng914170d22019-05-08 09:46:32147#### Requirements
148
149Enums logged in histograms must:
150
151- be prefixed with the comment:
152 ```c++
153 // These values are persisted to logs. Entries should not be renumbered and
154 // numeric values should never be reused.
155 ```
156- be numbered starting from `0`. Note this bullet point does *not* apply for
157 enums logged with sparse histograms.
Caitlin Fischerb5e94352020-10-27 17:34:50158- have enumerators with explicit values (`= 0`, `= 1`, `= 2`) to make it clear
Daniel Cheng914170d22019-05-08 09:46:32159 that the actual values are important. This also makes it easy to match the
160 values between the C++/Java definition and [histograms.xml](./histograms.xml).
161- not renumber or reuse enumerator values. When adding a new enumerator, append
162 the new enumerator to the end. When removing an unused enumerator, comment it
163 out, making it clear the value was previously used.
Gabriel Gauthier-Shalom06d5b552025-02-19 23:37:54164 - Note that enum labels may be revised in some cases; see
165 [Revising Histograms](#revising).
Daniel Cheng914170d22019-05-08 09:46:32166
167If your enum histogram has a catch-all / miscellaneous bucket, put that bucket
Caitlin Fischerb5e94352020-10-27 17:34:50168first (`= 0`). This makes the bucket easy to find on the dashboard if additional
169buckets are added later.
Daniel Cheng914170d22019-05-08 09:46:32170
171#### Usage
172
Ilya Shermanb6bd3c72020-04-15 23:08:15173*In C++*, define an `enum class` with a `kMaxValue` enumerator:
Daniel Cheng914170d22019-05-08 09:46:32174
Steven Holteecf841d2018-08-10 00:53:34175```c++
Hong Xu4b0bc44f2023-08-01 20:30:42176// These values are persisted to logs. Entries should not be renumbered and
177// numeric values should never be reused.
James Lee53e80dc2024-04-19 11:31:06178//
179// LINT.IfChange(NewTabPageAction)
Daniel Chengcda1df5b2018-03-30 21:30:16180enum class NewTabPageAction {
181 kUseOmnibox = 0,
182 kClickTitle = 1,
Daniel Cheng914170d22019-05-08 09:46:32183 // kUseSearchbox = 2, // no longer used, combined into omnibox
184 kOpenBookmark = 3,
Daniel Chengcda1df5b2018-03-30 21:30:16185 kMaxValue = kOpenBookmark,
186};
James Lee53e80dc2024-04-19 11:31:06187// LINT.ThenChange(//path/to/enums.xml:NewTabPageActionEnum)
Daniel Chengcda1df5b2018-03-30 21:30:16188```
Daniel Chengcda1df5b2018-03-30 21:30:16189
Sun Yuerud0739142024-12-18 20:19:44190The `LINT.IfChange` / `LINT.ThenChange` comments point between the code and XML
James Lee53e80dc2024-04-19 11:31:06191definitions of the enum, to encourage them to be kept in sync. See
192[guide](https://www.chromium.org/chromium-os/developer-library/guides/development/keep-files-in-sync/)
193and [more details](http://go/gerrit-ifthisthenthat).
194
Daniel Cheng914170d22019-05-08 09:46:32195`kMaxValue` is a special enumerator that must share the highest enumerator
196value, typically done by aliasing it with the enumerator with the highest
197value: clang automatically checks that `kMaxValue` is correctly set for `enum
198class`.
199
Takashi Toyoshima0b520762024-05-08 23:17:33200*In Mojo*, define an `enum` without a `kMaxValue` enumerator as `kMaxValue` is
201autogenerated for Mojo C++ bindings:
202
203```c++
204// These values are persisted to logs. Entries should not be renumbered and
205// numeric values should never be reused.
206//
207// LINT.IfChange(PreloadType)
208enum PrerenderType {
209 kPrefetch = 0,
210 // kPrerender = 1, // deprecated, revamped as kPrerender2
211 kNoStatePrefetch = 2,
212 kPrerender2 = 3,
213};
214// LINT.ThenChange(//path/to/enums.xml:PreloadType)
215```
216
217*In C++*, the histogram helpers use the `kMaxValue` convention, and the enum may
218be logged with:
Daniel Cheng914170d22019-05-08 09:46:32219
220```c++
Daniel Chengcda1df5b2018-03-30 21:30:16221UMA_HISTOGRAM_ENUMERATION("NewTabPageAction", action);
222```
Daniel Chengcda1df5b2018-03-30 21:30:16223
Daniel Cheng914170d22019-05-08 09:46:32224or:
225
Steven Holteecf841d2018-08-10 00:53:34226```c++
Daniel Cheng914170d22019-05-08 09:46:32227UmaHistogramEnumeration("NewTabPageAction", action);
Daniel Chengcda1df5b2018-03-30 21:30:16228```
Steven Holteecf841d2018-08-10 00:53:34229
Hong Xu365a4f72022-02-25 04:26:02230where `action` is an enumerator of the enumeration type `NewTabPageAction`.
231
Nate Fischer1f6efe52020-06-17 19:18:21232Logging histograms from Java should look similar:
233
234```java
235// These values are persisted to logs. Entries should not be renumbered and
236// numeric values should never be reused.
237@IntDef({NewTabPageAction.USE_OMNIBOX, NewTabPageAction.CLICK_TITLE,
238 NewTabPageAction.OPEN_BOOKMARK})
239private @interface NewTabPageAction {
240 int USE_OMNIBOX = 0;
241 int CLICK_TITLE = 1;
242 // int USE_SEARCHBOX = 2; // no longer used, combined into omnibox
243 int OPEN_BOOKMARK = 3;
244 int COUNT = 4;
245}
246
247// Using a helper function is optional, but avoids some boilerplate.
248private static void logNewTabPageAction(@NewTabPageAction int action) {
249 RecordHistogram.recordEnumeratedHistogram(
250 "NewTabPageAction", action, NewTabPageAction.COUNT);
251}
252```
253
Hong Xu77292842022-05-18 06:43:59254Finally, regardless of the programming language you are using, add the
James Lee53e80dc2024-04-19 11:31:06255definition of the enumerator to [enums.xml](./enums.xml), and add linter checks
256to keep the C++/Java and XML values in sync:
257
258```xml
259<!-- LINT.IfChange(NewTabPageActionEnum) -->
260<enum name="NewTabPageActionEnum">
261 ...
262</enum>
263<!-- LINT.ThenChange(//path/to/cpp_definition.h:NewTabPageAction) -->
264```
Hong Xu77292842022-05-18 06:43:59265
Daniel Cheng914170d22019-05-08 09:46:32266#### Legacy Enums
267
268**Note: this method of defining histogram enums is deprecated. Do not use this
Ilya Shermanb6bd3c72020-04-15 23:08:15269for new enums *in C++*.**
Daniel Cheng914170d22019-05-08 09:46:32270
Chris Blumebdca7ca2020-06-08 15:48:35271Many legacy enums define a `kCount` sentinel, relying on the compiler to
Daniel Cheng914170d22019-05-08 09:46:32272automatically update it when new entries are added:
273
Steven Holteecf841d2018-08-10 00:53:34274```c++
Daniel Chengcda1df5b2018-03-30 21:30:16275enum class NewTabPageAction {
276 kUseOmnibox = 0,
277 kClickTitle = 1,
Daniel Cheng914170d22019-05-08 09:46:32278 // kUseSearchbox = 2, // no longer used, combined into omnibox
279 kOpenBookmark = 3,
Daniel Chengcda1df5b2018-03-30 21:30:16280 kCount,
281};
Daniel Cheng914170d22019-05-08 09:46:32282```
Steven Holteecf841d2018-08-10 00:53:34283
Daniel Cheng914170d22019-05-08 09:46:32284These enums must be recorded using the legacy helpers:
285
286```c++
Daniel Chengcda1df5b2018-03-30 21:30:16287UMA_HISTOGRAM_ENUMERATION("NewTabPageAction", action, NewTabPageAction::kCount);
288```
289
Daniel Cheng914170d22019-05-08 09:46:32290or:
291
292```c++
293UmaHistogramEnumeration("NewTabPageAction", action, NewTabPageAction::kCount);
294```
mpearsonb36013be2017-02-10 20:10:54295
Matt Giucaf3e0e2532017-10-03 23:07:52296### Flag Histograms
297
298When adding a new flag in
299[about_flags.cc](../../../chrome/browser/about_flags.cc), you need to add a
Caitlin Fischerb5e94352020-10-27 17:34:50300corresponding entry to [enums.xml](./enums.xml). This is automatically verified
301by the `AboutFlagsHistogramTest` unit test.
Matt Giucaf3e0e2532017-10-03 23:07:52302
303To add a new entry:
304
manukh26fe9852022-10-04 23:38:143051. After adding flags
306 to [about_flags.cc](../../../chrome/browser/about_flags.cc),
307 run `generate_flag_enums.py --feature <your awesome feature>` or
308 simply `generate_flag_enums.py` (slower).
309
310You can alternatively follow these steps:
311
Matt Giucaf3e0e2532017-10-03 23:07:523121. Edit [enums.xml](./enums.xml), adding the feature to the `LoginCustomFlags`
Brett Wilsonf4d58772017-10-30 21:37:57313 enum section, with any unique value (just make one up, although whatever it
Caitlin Fischerb5e94352020-10-27 17:34:50314 is needs to appear in sorted order; `pretty_print.py` can do this for you).
Matt Giucaf3e0e2532017-10-03 23:07:523152. Build `unit_tests`, then run `unit_tests
Eric Lawrenced4d7d5c2023-05-09 20:48:25316 --gtest_filter=AboutFlagsHistogramTest.*` to compute the correct value.
Matt Giucaf3e0e2532017-10-03 23:07:523173. Update the entry in [enums.xml](./enums.xml) with the correct value, and move
Caitlin Fischerb5e94352020-10-27 17:34:50318 it so the list is sorted by value (`pretty_print.py` can do this for you).
Matt Giucaf3e0e2532017-10-03 23:07:523194. Re-run the test to ensure the value and ordering are correct.
320
321You can also use `tools/metrics/histograms/validate_format.py` to check the
322ordering (but not that the value is correct).
323
Alexei Svitkinedcf25c182024-09-20 17:59:09324Don't remove or modify entries when removing a flag; they are still used to
325decode data from previous Chrome versions.
Matt Giucaf3e0e2532017-10-03 23:07:52326
mpearson2b5f7e02016-10-03 21:27:03327### Count Histograms
328
329[histogram_macros.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h)
Caitlin Fischerfc138c82021-11-04 21:31:19330provides macros for some common count types, such as memory or elapsed time, in
Caitlin Fischerb5e94352020-10-27 17:34:50331addition to general count macros. These have reasonable default values; you
332seldom need to choose the number of buckets or histogram min. However, you still
333need to choose the histogram max (use the advice below).
mpearson2b5f7e02016-10-03 21:27:03334
Caitlin Fischerfc138c82021-11-04 21:31:19335If none of the default macros work well for you, please thoughtfully choose a
336min, max, and bucket count for your histogram using the advice below.
mpearson2b5f7e02016-10-03 21:27:03337
rkaplow6dfcb892016-10-04 14:04:27338#### Count Histograms: Choosing Min and Max
mpearson2b5f7e02016-10-03 21:27:03339
Caitlin Fischerfc138c82021-11-04 21:31:19340For the max, choose a value such that very few histogram samples exceed the max.
341If a sample is greater than or equal to the max value, it is put in an
342"overflow" bucket. If this bucket is too large, it can be difficult to compute
343statistics. One rule of thumb is that at most 1% of samples should be in the
Robert Kaplowcbc6fd62021-03-19 15:11:40344overflow bucket (and ideally, less). This allows analysis of the 99th
345percentile. Err on the side of too large a range versus too short a range.
Caitlin Fischerfc138c82021-11-04 21:31:19346Remember that if you choose poorly, you'll have to wait for another release
347cycle to fix it.
mpearson2b5f7e02016-10-03 21:27:03348
Caitlin Fischerfc138c82021-11-04 21:31:19349For the min, use 1 if you care about all possible values (zero and above). All
350histograms have an underflow bucket for emitted zeros, so a min of 1 is
351appropriate. Otherwise, choose the min appropriate for your particular
352situation.
mpearson2b5f7e02016-10-03 21:27:03353
rkaplow6dfcb892016-10-04 14:04:27354#### Count Histograms: Choosing Number of Buckets
mpearson2b5f7e02016-10-03 21:27:03355
Caitlin Fischerb5e94352020-10-27 17:34:50356Choose the smallest number of buckets that give you the granularity you need. By
Hong Xu3a229d832022-05-12 04:37:30357default, count histogram bucket sizes increase exponentially with respect to the
358value (i.e., exponential binning), so you can get fine granularity when the
359values are small yet still reasonable resolution when the values are larger. The
360macros default to 50 buckets (or 100 buckets for histograms with wide ranges),
361which is appropriate for most purposes. Because histograms pre-allocate all the
362buckets, the number of buckets selected directly dictates how much memory is
363used. Do not exceed 100 buckets without good reason (and consider whether
364[sparse histograms](#When-To-Use-Sparse-Histograms) might work better for you in
365that case—they do not pre-allocate their buckets).
rkaplow8a62ef62016-10-06 14:42:34366
Mark Pearson6be2f35c2018-08-14 07:06:02367### Timing Histograms
368
Yoshisato Yanagisawa4782e2f2024-04-19 00:50:34369You can easily emit a time duration (time delta) using base::UmaHistogramTimes,
370base::UmaHistogramMediumTimes, base::UmaHistogramLongTimes, and their friends.
371For the critical path, UMA_HISTOGRAM_TIMES, UMA_HISTOGRAM_MEDIUM_TIMES,
372UMA_HISTOGRAM_LONG_TIMES macros, and their friends, as well as helpers like
373SCOPED_UMA_HISTOGRAM_TIMER are also available. Many timing
Mark Pearson6be2f35c2018-08-14 07:06:02374histograms are used for performance monitoring; if this is the case for you,
375please read [this document about how to structure timing histograms to make
376them more useful and
Paul Jensen5107d9c2018-10-22 22:24:06377actionable](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/speed/diagnostic_metrics.md).
Mark Pearson6be2f35c2018-08-14 07:06:02378
Mark Pearson49928ec2018-06-05 20:15:49379### Percentage or Ratio Histograms
380
Caitlin Fischerb5e94352020-10-27 17:34:50381You can easily emit a percentage histogram using the UMA_HISTOGRAM_PERCENTAGE
382macro provided in
Mark Pearson49928ec2018-06-05 20:15:49383[histogram_macros.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h).
Caitlin Fischerb5e94352020-10-27 17:34:50384You can also easily emit any ratio as a linear histogram (for equally sized
385buckets).
Mark Pearson49928ec2018-06-05 20:15:49386
Caitlin Fischerb5e94352020-10-27 17:34:50387For such histograms, you want each value recorded to cover approximately the
388same span of time. This typically means emitting values periodically at a set
389time interval, such as every 5 minutes. We do not recommend recording a ratio at
390the end of a video playback, as video lengths vary greatly.
Mark Pearson49928ec2018-06-05 20:15:49391
Mark Pearson9be8bffa2020-03-03 19:08:02392It is okay to emit at the end of an animation sequence when what's being
Caitlin Fischerb5e94352020-10-27 17:34:50393animated is fixed / known. In this case, each value represents roughly the same
394span of time.
Mark Pearson9be8bffa2020-03-03 19:08:02395
Caitlin Fischerb5e94352020-10-27 17:34:50396Why? You typically cannot make decisions based on histograms whose values are
397recorded in response to an event that varies in length because such metrics can
398conflate heavy usage with light usage. It's easier to reason about metrics that
399avoid this source of bias.
Mark Pearson49928ec2018-06-05 20:15:49400
Caitlin Fischerb5e94352020-10-27 17:34:50401Many developers have been bitten by this. For example, it was previously common
402to emit an actions-per-minute ratio whenever Chrome was backgrounded. Precisely,
403these metrics computed the number of uses of a particular action during a Chrome
404session, divided by length of time Chrome had been open. Sometimes, the recorded
405rate was based on a short interaction with Chrome–a few seconds or a minute.
406Other times, the recorded rate was based on a long interaction, tens of minutes
407or hours. These two situations are indistinguishable in the UMA logs–the
408recorded values can be identical.
Mark Pearson49928ec2018-06-05 20:15:49409
Caitlin Fischerb5e94352020-10-27 17:34:50410The inability to distinguish these two qualitatively different settings make
411such histograms effectively uninterpretable and not actionable. Emitting at a
412regular interval avoids the issue. Each value represents the same amount of time
413(e.g., one minute of video playback).
Mark Pearson49928ec2018-06-05 20:15:49414
rkaplow8a62ef62016-10-06 14:42:34415### Local Histograms
416
Gayane Petrosyana6ee443c2018-05-17 21:39:54417Histograms can be added via [Local macros](https://codesearch.chromium.org/chromium/src/base/metrics/histogram_macros_local.h).
Caitlin Fischerb5e94352020-10-27 17:34:50418These still record locally, but are not uploaded to UMA and are therefore not
419available for analysis. This can be useful for metrics only needed for local
420debugging. We don't recommend using local histograms outside of that scenario.
rkaplow8a62ef62016-10-06 14:42:34421
422### Multidimensional Histograms
423
Caitlin Fischerb5e94352020-10-27 17:34:50424It is common to be interested in logging multidimensional data–where multiple
rkaplow8a62ef62016-10-06 14:42:34425pieces of information need to be logged together. For example, a developer may
426be interested in the counts of features X and Y based on whether a user is in
427state A or B. In this case, they want to know the count of X under state A,
428as well as the other three permutations.
429
430There is no general purpose solution for this type of analysis. We suggest
431using the workaround of using an enum of length MxN, where you log each unique
432pair {state, feature} as a separate entry in the same enum. If this causes a
Gayane Petrosyana6ee443c2018-05-17 21:39:54433large explosion in data (i.e. >100 enum entries), a [sparse histogram](#When-To-Use-Sparse-Histograms)
Caitlin Fischerb5e94352020-10-27 17:34:50434may be appropriate. If you are unsure of the best way to proceed, please contact
435someone from the OWNERS file.
Gayane Petrosyana6ee443c2018-05-17 21:39:54436
437## Histogram Expiry
438
Caitlin Fischerb5e94352020-10-27 17:34:50439Histogram expiry is specified by the `expires_after` attribute in histogram
Mark Pearson37c3c9a2023-06-29 17:17:30440descriptions in histograms.xml. It is a required attribute. The attribute can
441be specified as date in **YYYY-MM-DD** format or as Chrome milestone in
442**M**\*(e.g. M105) format. In the latter case, the actual expiry date is about
44312 weeks after that branch is cut, or basically when it is replaced on the
444"stable" channel by the following release.
Brian Whitefa0a3fa2019-05-13 16:58:11445
Mark Pearsonce4371c2021-03-15 23:57:42446After a histogram expires, it ceases to be displayed on the dashboard.
447Follow [these directions](#extending) to extend it.
Brian Whitefa0a3fa2019-05-13 16:58:11448
Caitlin Fischerb5e94352020-10-27 17:34:50449Once a histogram has expired, the code that records it becomes dead code and
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33450should be removed from the codebase. You should also [clean up](#obsolete) the
Alexei Svitkined4cbf402022-11-14 20:55:25451corresponding entry in histograms.xml. In _rare_ cases, a histogram may be
452expired intentionally while keeping the code around; such cases must be
Alexei Svitkine6fbe8ac2022-11-14 21:17:40453[annotated appropriately](#Intentionally-expired-histograms) in histograms.xml.
Gayane Petrosyana6ee443c2018-05-17 21:39:54454
Brian White8614f812019-02-07 21:07:01455In **rare** cases, the expiry can be set to "never". This is used to denote
Robert Kaplowcbc6fd62021-03-19 15:11:40456metrics of critical importance that are, typically, used for other reports. For
457example, all metrics of the
458"[heartbeat](https://uma.googleplex.com/p/chrome/variations)" are set to never
459expire. All metrics that never expire must have an XML comment describing why so
460that it can be audited in the future. Setting an expiry to "never" must be
461reviewed by [email protected].
Brian White8614f812019-02-07 21:07:01462
463```
464<!-- expires-never: "heartbeat" metric (internal: go/uma-heartbeats) -->
465```
466
Mark Pearson37c3c9a2023-06-29 17:17:30467It is never appropriate to set the expiry to "never" on a new histogram. Most
468new histograms don't turn out to have the properties the implementer wants,
469whether due to bugs in the implementation or simply an evolving understanding
470of what should be measured.
Gayane Petrosyana6ee443c2018-05-17 21:39:54471
Yoshisato Yanagisawa19d35ca2024-04-09 03:50:18472#### Guidelines on expiry
Gayane Petrosyana6ee443c2018-05-17 21:39:54473
Ilya Sherman67418ea2019-11-27 01:28:23474Here are some guidelines for common scenarios:
Gayane Petrosyana6ee443c2018-05-17 21:39:54475
Yoshisato Yanagisawa19d35ca2024-04-09 03:50:18476* If the listed owner moved to a different project, find a new owner.
Ilya Sherman67418ea2019-11-27 01:28:23477* If neither the owner nor the team uses the histogram, remove it.
478* If the histogram is not in use now, but might be useful in the far future,
479 remove it.
480* If the histogram is not in use now, but might be useful in the near
Brian Whitedb68067b2021-10-13 18:27:28481 future, pick ~3 months (also ~3 milestones) ahead.
Yoshisato Yanagisawa19d35ca2024-04-09 03:50:18482* Otherwise, pick an expiry that is reasonable for how long the metric should
483 be used, up to a year.
Ilya Sherman67418ea2019-11-27 01:28:23484
Brian Whitedb68067b2021-10-13 18:27:28485We also have a tool that automatically extends expiry dates. The most frequently
486accessed histograms, currently 99%, have their expirations automatically
487extended every Tuesday to 6 months from the date of the run. Googlers can view
488the [design
489doc](https://docs.google.com/document/d/1IEAeBF9UnYQMDfyh2gdvE7WlUKsfIXIZUw7qNoU89A4)
490of the program that does this. The bottom line is: If the histogram is being
491checked, it should be extended without developer interaction.
Gayane Petrosyana6ee443c2018-05-17 21:39:54492
Yoshisato Yanagisawa19d35ca2024-04-09 03:50:18493#### How to choose expiry for new histograms
494
495In general, set an expiry that is reasonable for how long the metric should
496be used, up to a year.
497
498Some common cases:
499
500* When adding a histogram to evaluate a feature launch, set an expiry date
501 consistent with the expected feature launch date.
502* If you expect the histogram to be useful for an indefinite time, set an
503 expiry date up to 1 year out. This gives a chance to re-evaluate whether
504 the histogram indeed proved to be useful.
505* Otherwise, 3-6 months (3-6 milestones) is typically a good choice.
506
Mark Pearsonce4371c2021-03-15 23:57:42507#### How to extend an expired histogram {#extending}
508
509You can revive an expired histogram by setting the expiration date to a
510date in the future.
511
512There's some leeway here. A client may continue to send data for that
513histogram for some time after the official expiry date so simply bumping
514the 'expires_after' date at HEAD may be sufficient to resurrect it without
515any data discontinuity.
516
517If a histogram expired more than a month ago (for histograms with an
518expiration date) or more than one milestone ago (for histograms with
519expiration milestones; this means top-of-tree is two or more milestones away
520from expired milestone), then you may be outside the safety window. In this
521case, when extending the histogram add to the histogram description a
522message: "Warning: this histogram was expired from DATE to DATE; data may be
523missing." (For milestones, write something similar.)
524
525When reviving a histogram outside the safety window, realize the change to
526histograms.xml to revive it rolls out with the binary release. It takes
527some time to get to the stable channel.
528
529It you need to revive it faster, the histogram can be re-enabled via adding to
530the [expired histogram allowlist](#Expired-histogram-allowlist).
531
Gayane Petrosyana6ee443c2018-05-17 21:39:54532### Expired histogram notifier
533
Caitlin Fischerb5e94352020-10-27 17:34:50534The expired histogram notifier notifies histogram owners before their histograms
535expire by creating crbugs, which are assigned to owners. This allows owners to
536extend the lifetime of their histograms, if needed, or deprecate them. The
537notifier regularly checks all histograms across the histograms.xml files and
538identifies expired or soon-to-be expired histograms. It then creates or updates
539crbugs accordingly.
Gayane Petrosyana6ee443c2018-05-17 21:39:54540
Caitlin Fischer9f4841052020-11-04 21:02:44541### Expired histogram allowlist
Gayane Petrosyana6ee443c2018-05-17 21:39:54542
Caitlin Fischerb5e94352020-10-27 17:34:50543If a histogram expires but turns out to be useful, you can add the histogram's
Alexei Svitkined4cbf402022-11-14 20:55:25544name to the allowlist to re-enable logging for it, until the updated expiration
545date reaches the Stable channel. When doing so, update the histogram's summary
546to document the period during which the histogram's data is incomplete. To add a
547histogram to the allowlist, see the internal documentation:
Caitlin Fischerb5e94352020-10-27 17:34:50548[Histogram Expiry](https://goto.google.com/histogram-expiry-gdoc).
mpearson2b5f7e02016-10-03 21:27:03549
Alexei Svitkine6fbe8ac2022-11-14 21:17:40550### Intentionally expired histograms
Alexei Svitkined4cbf402022-11-14 20:55:25551
552In **rare** cases, a histogram may be expired intentionally while keeping the
553code around. For example, this can be useful for diagnostic metrics that are
554occasionally needed to investigate specific bugs, but do not need to be reported
555otherwise.
556
557To avoid such histograms to be flagged for code clean up, they must be annotated
558in the histograms.xml with the `expired_intentionally` tag as follows:
559
560```xml
561<histogram name="Tab.Open" enum="TabType" expires_after="M100">
562 <expired_intentionally>Kept as a diagnostic metric.</expired_intentionally>
563 <owner>[email protected]</owner>
564 <summary>Histogram summary.</summary>
565</histogram>
566```
567
mpearson72a5c91392017-05-09 22:49:44568## Testing
mpearson2b5f7e02016-10-03 21:27:03569
Caitlin Fischerb5e94352020-10-27 17:34:50570Test your histograms using `chrome://histograms`. Make sure they're being
rkaplow6dfcb892016-10-04 14:04:27571emitted to when you expect and not emitted to at other times. Also check that
Caitlin Fischerb5e94352020-10-27 17:34:50572the values emitted to are correct. Finally, for count histograms, make sure
rkaplow6dfcb892016-10-04 14:04:27573that buckets capture enough precision for your needs over the range.
mpearson2b5f7e02016-10-03 21:27:03574
Ivan Sandrk8ffc5832018-07-09 12:34:58575Pro tip: You can filter the set of histograms shown on `chrome://histograms` by
Luc Nguyenb1324cb2022-12-17 16:23:41576appending to the URL. For example, `chrome://histograms/UserActions` shows
577only histograms whose names contain "UserActions", such as
578"UMA.UserActionsCount".
Ivan Sandrk8ffc5832018-07-09 12:34:58579
mpearson72a5c91392017-05-09 22:49:44580In addition to testing interactively, you can have unit tests examine the
Caitlin Fischerb5e94352020-10-27 17:34:50581values emitted to histograms. See [histogram_tester.h](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_tester.h)
mpearson72a5c91392017-05-09 22:49:44582for details.
mpearson2b5f7e02016-10-03 21:27:03583
Luc Nguyenb1324cb2022-12-17 16:23:41584See also `chrome://metrics-internals` ([docs](https://chromium.googlesource.com/chromium/src/+/master/components/metrics/debug/README.md))
585for more thorough manual testing if needed.
586
Robert Kaplow82027632023-02-13 16:31:52587By default, histograms in unit or browser tests will not be actually uploaded.
588In general, you can rely on the UMA infrastructure to upload the metrics correctly.
589
Alan Screen291bc9a2023-06-27 21:16:49590### Don't Use Histograms to Prove Main Logic Correctness
591
592Do not rely upon using histograms in tests as a way to prove correctness of
593your main program logic. If a unit or browser test uses a histogram count as a
594way to validate logic then that test coverage would be lost if the histogram is
595deleted after it has expired. That situation would prevent cleanup of the
596histogram. Construct your tests using other means to validate your general
597logic, and only use
598[`HistogramTester`](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_tester.h)
599to verify that the histogram values are being generated as you would expect.
600
Dana Friedac15ff82024-04-02 21:19:34601### Verify Enum and Variant Values
602
603If you have <enum> or <variant> entries that need to be updated to match code,
604you can use
605[HistogramEnumReader](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_enum_reader.h)
606or
Moe Ahmadi5d5aa1d2025-04-01 14:39:47607[HistogramVariantsReader](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_variants_reader.h)
Dana Friedac15ff82024-04-02 21:19:34608to read and verify the expected values in a unit test. This prevents a mismatch
609between code and histogram data from slipping through CQ.
610
611For an example, see
612[BrowserUserEducationServiceTest.CheckFeaturePromoHistograms](https://cs.chromium.org/chromium/src/chrome/browser/ui/views/user_education/browser_user_education_service_unittest.cc).
613
Mark Pearson4c4bc972018-05-16 20:01:06614## Interpreting the Resulting Data
615
616The top of [go/uma-guide](http://go/uma-guide) has good advice on how to go
Caitlin Fischerb5e94352020-10-27 17:34:50617about analyzing and interpreting the results of UMA data uploaded by users. If
Mark Pearson4c4bc972018-05-16 20:01:06618you're reading this page, you've probably just finished adding a histogram to
619the Chromium source code and you're waiting for users to update their version of
Caitlin Fischerb5e94352020-10-27 17:34:50620Chrome to a version that includes your code. In this case, the best advice is
621to remind you that users who update frequently / quickly are biased. Best take
Mark Pearson4c4bc972018-05-16 20:01:06622the initial statistics with a grain of salt; they're probably *mostly* right but
623not entirely so.
624
Gabriel Gauthier-Shalom06d5b552025-02-19 23:37:54625## Revising Histograms {#revising}
mpearson72a5c91392017-05-09 22:49:44626
Robert Kaplowcbc6fd62021-03-19 15:11:40627When changing the semantics of a histogram (when it's emitted, what the buckets
Mark Schillacid88d4532025-05-01 15:39:20628represent, the bucket range or number of buckets for numeric histograms, etc.),
629create a new histogram with a new name. A new histogram name is not required
630when adding a new value to an enum if users will not move between buckets, and
631bucket proportion is not meaningful. Otherwise analysis that mixes the data pre-
632and post- change may be misleading. If the histogram name is still the best name
633choice, the recommendation is to simply append a '2' to the name. See
634[Cleaning Up Histogram Entries](#obsolete) for details on how to handle the XML
635changes.
mpearson2b5f7e02016-10-03 21:27:03636
Gabriel Gauthier-Shalom06d5b552025-02-19 23:37:54637Changes to a histogram are allowed in some cases when the semantics have not
638changed at all. Here are some examples that would be allowed:
639- A histogram's summary can be rewritten to be more accurate.
640- An enum bucket's label can be changed, as long it still refers to the same
641 thing that it did before, e.g. if an enum listed some manufacturer's products,
642 and the manufacturer later renamed one of them.
643 - Note that downstream tooling will apply the updated label to past data
644 retroactively.
645
mpearson72a5c91392017-05-09 22:49:44646## Deleting Histograms
mpearson2b5f7e02016-10-03 21:27:03647
Caitlin Fischerb5e94352020-10-27 17:34:50648Please delete code that emits to histograms that are no longer needed.
649Histograms take up memory. Cleaning up histograms that you no longer care
650about is good! But see the note below on
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33651[Cleaning Up Histogram Entries](#obsolete).
mpearson2b5f7e02016-10-03 21:27:03652
653## Documenting Histograms
654
Darren Shenda91dc752023-03-01 05:28:30655Document histograms in an appropriate [metadata/foo/histograms.xml](https://source.chromium.org/search?q=f:metadata%2F.*%2Fhistograms.xml&ss=chromium%2Fchromium%2Fsrc)
656file.
657
658There is also a [google-internal version of the file](https://goto.google.com/chrome-histograms-internal)
659for two cases:
660
661* The histogram is confidential (an accurate description about how to interpret
662 the histogram would reveal information about Google's plans). In this case,
663 you must only document the histogram in the internal version.
664* The corresponding code that emits the histogram is internal (added only to
665 Chrome code, not to Chromium code). In this case, you may document the
666 histogram in either the internal or external version.
Mark Pearson159c38972018-06-05 19:44:08667
mpearson2b5f7e02016-10-03 21:27:03668### Add Histogram and Documentation in the Same Changelist
669
vapier52b9aba2016-12-14 06:09:25670If possible, please add the [histograms.xml](./histograms.xml) description in
Caitlin Fischerb5e94352020-10-27 17:34:50671the same changelist in which you add the histogram-emitting code. This has
672several benefits. One, it sometimes happens that the
vapier52b9aba2016-12-14 06:09:25673[histograms.xml](./histograms.xml) reviewer has questions or concerns about the
674histogram description that reveal problems with interpretation of the data and
Caitlin Fischerb5e94352020-10-27 17:34:50675call for a different recording strategy. Two, it allows the histogram reviewer
vapier52b9aba2016-12-14 06:09:25676to easily review the emission code to see if it comports with these best
Caitlin Fischerb5e94352020-10-27 17:34:50677practices and to look for other errors.
mpearson2b5f7e02016-10-03 21:27:03678
679### Understandable to Everyone
680
681Histogram descriptions should be roughly understandable to someone not familiar
Caitlin Fischerb5e94352020-10-27 17:34:50682with your feature. Please add a sentence or two of background if necessary.
mpearson2b5f7e02016-10-03 21:27:03683
Robert Kaplowcbc6fd62021-03-19 15:11:40684Note any caveats associated with your histogram in the summary. For example, if
685the set of supported platforms is surprising, such as if a desktop feature is
686not available on Mac, the summary should explain where it is recorded. It is
687also common to have caveats along the lines of "this histogram is only recorded
688if X" (e.g., upon a successful connection to a service, a feature is enabled by
689the user).
690
mpearson2b5f7e02016-10-03 21:27:03691
692### State When It Is Recorded
693
694Histogram descriptions should clearly state when the histogram is emitted
695(profile open? network request received? etc.).
696
Mark Pearsond8fc9fd22021-03-12 20:18:58697Some histograms record error conditions. These should be clear about whether
698all errors are recorded or only the first. If only the first, the histogram
699description should have text like:
700```
701In the case of multiple errors, only the first reason encountered is recorded. Refer
702to Class::FunctionImplementingLogic() for details.
703```
704
Ilya Sherman470c95a2020-09-21 23:05:43705### Provide Clear Units or Enum Labels
706
707For enumerated histograms, including boolean and sparse histograms, provide an
708`enum=` attribute mapping enum values to semantically contentful labels. Define
709the `<enum>` in enums.xml if none of the existing enums are a good fit. Use
710labels whenever they would be clearer than raw numeric values.
711
712For non-enumerated histograms, include a `units=` attribute. Be specific:
713e.g. distinguish "MB" vs. "MiB", refine generic labels like "counts" to more
714precise labels like "pages", etc.
715
jsbellda3a66c2017-02-09 21:40:32716### Owners
rkaplow8a62ef62016-10-06 14:42:34717
Caitlin Fischer254a12f72019-07-31 20:57:03718Histograms need owners, who are the experts on the metric and the points of
719contact for any questions or maintenance tasks, such as extending a histogram's
720expiry or deprecating the metric.
rkaplow8a62ef62016-10-06 14:42:34721
Caitlin Fischer254a12f72019-07-31 20:57:03722Histograms must have a primary owner and may have secondary owners. A primary
Sun Yuerud0739142024-12-18 20:19:44723owner is a Googler with an `@google.com` or `@chromium.org` email address, e.g.
724`<owner>[email protected]</owner>`, who is ultimately responsible for
725maintaining the metric. Secondary owners may be other individuals familiar with
726the implementation or the semantics of the metric, or a dev team mailing list,
727e.g. `<owner>[email protected]</owner>`, or paths to OWNERS files, e.g.
728`<owner>src/directory/OWNERS</owner>`. Do not put a `@chromium.org` group
729containing public users as an owner, since users of a feature have no knowledge
730of the codebase, can't perform any of the maintenance duties, nor should they be
731notified of any change to the histogram.
Mark Pearson74c53212019-03-08 00:34:08732
Caitlin Fischer254a12f72019-07-31 20:57:03733It's a best practice to list multiple owners, so that there's no single point
734of failure for histogram-related questions and maintenance tasks. If you are
735using a metric heavily and understand it intimately, feel free to add yourself
Caitlin Fischerb5e94352020-10-27 17:34:50736as an owner.
Mark Pearson74c53212019-03-08 00:34:08737
Caitlin Fischer254a12f72019-07-31 20:57:03738Notably, owners are asked to determine whether histograms have outlived their
Caitlin Fischerb5e94352020-10-27 17:34:50739usefulness. When a histogram is nearing expiry, a robot files a reminder bug in
740Monorail. It's important that somebody familiar with the histogram notices and
741triages such bugs!
rkaplow8a62ef62016-10-06 14:42:34742
Ilya Shermanf64bca252020-11-10 23:16:24743Tip: When removing someone from the owner list for a histogram, it's a nice
744courtesy to ask them for approval.
745
Caitlin Fischerfeafb4392020-10-05 21:10:07746### Components
747
Ariel Zhang62ee3f42024-02-26 23:25:29748Histograms may be associated with a component, which can help make sure that
Caitlin Fischerfeafb4392020-10-05 21:10:07749histogram expiry bugs don't fall through the cracks.
750
Ariel Zhang62ee3f42024-02-26 23:25:29751A histogram is associated with the `buganizer_public` component listed in the
752DIR_METADATA file adjacent to the histograms.xml file if present.
753
754There are two other ways in which components may be associated with a
755histogram. The first way is to add a tag containing the component ID to a
756histogram or histogram suffix, e.g. <component>1456399</component>. The second
757way is to specify an OWNERS file as a secondary owner for a histogram. If the
758OWNERS file has an adjacent DIR_METADATA file that contains a
759`buganizer_public` component, then that component is associated with the
760histogram. If there isn't a parallel DIR_METADATA file with such a component,
761but an ancestor directory has one, then the ancestor directory's component is
762used.
763
764If more than one component is associated with a histogram, <component> tag is
765favored over adjacent DIR_METADATA file and over OWNERS file.
766
767**Note:** For non-Chromium Issue Tracker (ChromeOS Public Tracker or internal)
768components, make sure [email protected] has access to create and
769update issues.
770
Caitlin Fischerfeafb4392020-10-05 21:10:07771
Sun Yueru39385712023-02-09 20:11:08772### Improvement Direction
773For some histograms, an increase or a decrease in the reported values can be
774associated with either an improvement or a deterioration. For example, if you
775are tracking page load speed, then seeing your metrics tracking page load time
776in milliseconds getting gradually larger values, perhaps as the result of a
777Finch study, may signify worse performance; on the contrary, seeing a reduction
778in the page load speed may indicate an improvement. You can provide this
779information on the movement direction by adding a tag
780 `<improvement direction="LOWER_IS_BETTER"/>` within your `<histogram>`. The
781opposite is `<improvement direction="HIGHER_IS_BETTER"/>`.
782
783For other histograms where there may not be a movement direction that's clearly
784better, you can set `<improvement direction="NEITHER_IS_BETTER"/>`.
785
786This `<improvement>` tag is optional. You can also add/delete this tag or make a
787correction to its `direction` attribute any time.
788
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33789### Cleaning Up Histogram Entries {#obsolete}
mpearson2b5f7e02016-10-03 21:27:03790
Alexei Svitkine7bfb6702023-11-28 18:18:24791When the code to log a histogram is deleted, its corresponding histograms.xml
792entry should also be removed. Past histogram data will still be available for
793viewing on Google's internal UMA dashboard.
Pavol Marko17ed24e2023-09-11 09:43:15794
Alexei Svitkine7bfb6702023-11-28 18:18:24795The CL to remove one or more histograms can also specify an obsoletion message
796through special syntax in the CL description. This also applies to variants of a
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33797[patterned histogram](#Patterned-Histograms) and to suffix entries for a
798suffixed histogram.
Mark Pearson2a311c52019-03-19 21:47:01799
Ariel Zhanged17ef22023-05-18 16:42:48800The changelist that obsoletes a histogram entry should be reviewed by all
801current owners.
Mark Pearson2a311c52019-03-19 21:47:01802
Ariel Zhanged17ef22023-05-18 16:42:48803#### Remove the Entry
Mark Pearson2a311c52019-03-19 21:47:01804
Ariel Zhanged17ef22023-05-18 16:42:48805Delete the entry in the histograms.xml file.
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33806
Gabriel Gauthier-Shaloma7394aa2022-02-14 16:33:37807* In some cases there may be artifacts that remain, with some examples being:
Charlie Harrison1ad2f852023-11-06 18:22:23808 * Empty `<token>` blocks, or individual `<variant>`s.
Gabriel Gauthier-Shaloma7394aa2022-02-14 16:33:37809 * `<enum>` blocks from enums.xml that are no longer used.
Alexei Svitkine7bfb6702023-11-28 18:18:24810 * Suffix entries in `histogram_suffixes_list.xml`.
Gabriel Gauthier-Shaloma7394aa2022-02-14 16:33:37811* Please remove these artifacts if you find them.
Sun Yueruf81cee32023-01-19 01:52:58812 * **Exception**: please update the label of `<int value=... label=... />` with
813 the `(Obsolete) ` prefix, e.g.
814 `<int value="1" label="(Obsolete) Navigation failed. Removed in 2023/01."/>`
815 rather than deleting them, if the surrounding `<enum>` block is not being
816 deleted.
Ariel Zhanged17ef22023-05-18 16:42:48817
818#### Add an Obsoletion Message
819
Will Harris0874e552023-08-25 16:09:44820An obsoletion message is displayed on the dashboard and provides developers
821context for why the histogram was removed and, if applicable, which histogram
822it was replaced by.
823
Alexei Svitkine7bfb6702023-11-28 18:18:24824**Note:** You can skip this step if the histogram is expired. This is because
825tooling automatically records the date and milestone of a histogram's
Ariel Zhangd111b722023-12-12 15:48:58826removal.
Ariel Zhang1cd268202023-07-14 19:30:56827
Will Harris0874e552023-08-25 16:09:44828You can provide a custom obsoletion message for a removed histogram via tags
829on the CL description:
Ariel Zhanged17ef22023-05-18 16:42:48830
831* Add the obsoletion message in the CL description in the format
Alexei Svitkine7bfb6702023-11-28 18:18:24832 `OBSOLETE_HISTOGRAM[histogram name]=message`, e.g.:
833 `OBSOLETE_HISTOGRAM[Tab.Count]=Replaced by Tab.Count2`
834* To add the same obsoletion message to all the histograms removed in the CL,
835 you can use `OBSOLETE_HISTOGRAMS=message`, e.g.:
836 `OBSOLETE_HISTOGRAMS=Patterned histogram Hist.{Token} is replaced by Hist.{Token}.2`
Ariel Zhang7b8cbf92023-06-21 22:24:14837* **Notes:**
Ariel Zhangd111b722023-12-12 15:48:58838 * **The full tag should be put on a single line, even if it is longer than the
839 maximum CL description width.**
Ariel Zhang1cd268202023-07-14 19:30:56840 * You can add multiple obsoletion message tags in one CL.
Alexei Svitkine7bfb6702023-11-28 18:18:24841 * `OBSOLETE_HISTOGRAMS` messages will be overwritten by histogram-specific
842 ones, if present.
843* You could also include information about why the histogram was removed. For
844 example, you might indicate how the histogram's summary did not accurately
845 describe the collected data.
846* If the histogram is being replaced, include the name of the replacement and
847 make sure that the new description is different from the original to reflect
848 the change between versions.
Ilya Sherman8f0034a2020-07-22 22:06:34849
Ilya Sherman9e22dea2020-10-05 22:32:36850### Patterned Histograms
Ilya Shermanf54104b2017-07-12 23:45:47851
852It is sometimes useful to record several closely related metrics, which measure
Ilya Sherman9e22dea2020-10-05 22:32:36853the same type of data, with some minor variations. You can declare the metadata
854for these concisely using patterned histograms. For example:
Ilya Shermanf54104b2017-07-12 23:45:47855
Ilya Sherman9e22dea2020-10-05 22:32:36856```xml
Jared Saul73a9daaf2021-05-04 15:33:02857<histogram name="Pokemon.{Character}.EfficacyAgainst{OpponentType}"
Robert Kaplowe1430ce2021-03-25 19:02:18858 units="multiplier" expires_after="M95">
Ilya Sherman9e22dea2020-10-05 22:32:36859 <owner>[email protected]</owner>
860 <owner>[email protected]</owner>
861 <summary>
862 The efficacy multiplier for {Character} against an opponent of
863 {OpponentType} type.
864 </summary>
865 <token key="Character">
866 <variant name="Bulbasaur"/>
867 <variant name="Charizard"/>
868 <variant name="Mewtwo"/>
869 </token>
870 <token key="OpponentType">
871 <variant name="Dragon" summary="dragon"/>
872 <variant name="Flying" summary="flappity-flap"/>
873 <variant name="Psychic" summary="psychic"/>
874 <variant name="Water" summary="water"/>
875 </token>
876</histogram>
877```
878
879This example defines metadata for 12 (= 3 x 4) concrete histograms, such as
880
881```xml
Robert Kaplowe1430ce2021-03-25 19:02:18882<histogram name="Pokemon.Charizard.EfficacyAgainstWater"
883 units="multiplier" expires_after="M95">
Ilya Sherman9e22dea2020-10-05 22:32:36884 <owner>[email protected]</owner>
885 <owner>[email protected]</owner>
886 <summary>
887 The efficacy multiplier for Charizard against an opponent of water type.
888 </summary>
889</histogram>
890```
891
James Lee53e80dc2024-04-19 11:31:06892Each token `<variant>` defines what text should be substituted for it,
893both in the histogram name and in the summary text. The name part gets
894substituted into the histogram name; the summary part gets substituted in
Mark Pearson268ea6b2021-09-28 00:44:45895the summary field (the histogram description). As shorthand, a
896`<variant>` that omits the `summary` attribute substitutes the value of
897the `name` attribute in the histogram's `<summary>` text as well.
Ilya Sherman9e22dea2020-10-05 22:32:36898
899*** promo
900Tip: You can declare an optional token by listing an empty name: `<variant
901name="" summary="aggregated across all breakdowns"/>`. This can be useful when
902recording a "parent" histogram that aggregates across a set of breakdowns.
903***
904
905You can use the `<variants>` tag to define a set of `<variant>`s out-of-line.
906This is useful for token substitutions that are shared among multiple families
Ariel Zhang6adadaf2023-06-07 14:55:15907of histograms within the same file. See
Ilya Sherman9e22dea2020-10-05 22:32:36908[histograms.xml](https://source.chromium.org/search?q=file:histograms.xml%20%3Cvariants)
909for examples.
910
Joe Masonb468cc42022-06-21 18:02:16911*** promo
912Warning: The `name` attribute of the `<variants>` tag is globally scoped, so
Ariel Zhang6adadaf2023-06-07 14:55:15913use detailed names to avoid collisions. The `<variants>` defined should only
914be used within the file.
Joe Masonb468cc42022-06-21 18:02:16915***
916
Caitlin Fischerb5e94352020-10-27 17:34:50917By default, a `<variant>` inherits the owners declared for the patterned
Ilya Sherman9e22dea2020-10-05 22:32:36918histogram. Each variant can optionally override the inherited list with custom
919owners:
920```xml
921<variant name="SubteamBreakdown" ...>
922 <owner>[email protected]</owner>
923 <owner>[email protected]</owner>
924</variant>
925```
Mark Pearsona0109122018-05-30 18:23:05926
Ilya Sherman9e22dea2020-10-05 22:32:36927*** promo
Oksana Zhuravlova5242ad22021-02-19 00:14:20928Tip: You can run `print_expanded_histograms.py --pattern=` to show all generated
Weilun Shibac61d9d32020-11-12 02:40:26929histograms by patterned histograms or histogram suffixes including their
930summaries and owners. For example, this can be run (from the repo root) as:
931```
Oksana Zhuravlova5242ad22021-02-19 00:14:20932./tools/metrics/histograms/print_expanded_histograms.py --pattern=^UMA.A.B
Weilun Shibac61d9d32020-11-12 02:40:26933```
934***
935
936*** promo
Ilya Sherman9e22dea2020-10-05 22:32:36937Tip: You can run `print_histogram_names.py --diff` to enumerate all the
938histogram names that are generated by a particular CL. For example, this can be
939run (from the repo root) as:
Charlie Harrison90407d92020-05-19 23:57:32940```
Egor Pasko5ec32b72021-07-23 14:34:22941./tools/metrics/histograms/print_histogram_names.py --diff origin/main
Charlie Harrison90407d92020-05-19 23:57:32942```
Ilya Sherman9e22dea2020-10-05 22:32:36943***
944
945For documentation about the `<histogram_suffixes>` syntax, which is deprecated,
946see
947https://chromium.googlesource.com/chromium/src/+/refs/tags/87.0.4270.1/tools/metrics/histograms/one-pager.md#histogram-suffixes-deprecated-in-favor-of-pattern-histograms
Charlie Harrison90407d92020-05-19 23:57:32948
mpearson2b5f7e02016-10-03 21:27:03949## When To Use Sparse Histograms
950
Caitlin Fischerb5e94352020-10-27 17:34:50951Sparse histograms are well-suited for recording counts of exact sample values
952that are sparsely distributed over a large range. They can be used with enums
Ilya Sherman1eee82c4c2017-12-08 01:22:19953as well as regular integer values. It is often valuable to provide labels in
954[enums.xml](./enums.xml).
mpearson2b5f7e02016-10-03 21:27:03955
956The implementation uses a lock and a map, whereas other histogram types use a
957vector and no lock. It is thus more costly to add values to, and each value
958stored has more overhead, compared to the other histogram types. However it
959may be more efficient in memory if the total number of sample values is small
960compared to the range of their values.
961
Mark Pearsoned73f1f2019-03-22 18:00:12962Please talk with the metrics team if there are more than a thousand possible
963different values that you could emit.
964
rkaplow6dfcb892016-10-04 14:04:27965For more information, see [sparse_histograms.h](https://cs.chromium.org/chromium/src/base/metrics/sparse_histogram.h).
Caitlin Fischerb466a042019-07-31 21:41:46966
Ilya Shermanf64bca252020-11-10 23:16:24967
Robert Kaplow6be6fbf2021-04-19 17:30:38968# Becoming a Metrics Reviewer
Caitlin Fischerb466a042019-07-31 21:41:46969
Jared Saul73a9daaf2021-05-04 15:33:02970Any Chromium committer who is also a Google employee is eligible to become a
971metrics reviewer. Please follow the instructions at [go/reviewing-metrics](https://goto.google.com/reviewing-metrics).
972This consists of reviewing our training materials and passing an informational
973quiz. Since metrics have a direct impact on internal systems and have privacy
Robert Kaplow6be6fbf2021-04-19 17:30:38974considerations, we're currently only adding Googlers into this program.
975
976
977# Reviewing Metrics CLs
Ilya Shermanf64bca252020-11-10 23:16:24978
Robert Kaplowcbc6fd62021-03-19 15:11:40979If you are a metric OWNER, you have the serious responsibility of ensuring
980Chrome's data collection is following best practices. If there's any concern
981about an incoming metrics changelist, please escalate by assigning to
982[email protected].
983
Ilya Shermanf64bca252020-11-10 23:16:24984When reviewing metrics CLs, look at the following, listed in approximate order
985of importance:
986
Mark Pearson4bd7ca892024-12-11 23:35:08987## Privacy and Purpose
Ilya Shermanf64bca252020-11-10 23:16:24988
Mark Pearson4bd7ca892024-12-11 23:35:08989Google has policies restricting what data can be collected and for what purpose.
990Googlers, make sure the logging abides by the principles at
991go/uma-privacy#principles.
Ilya Shermanf64bca252020-11-10 23:16:24992
Mark Pearson4bd7ca892024-12-11 23:35:08993Furthermore, if anything tickles your privacy senses or provokes any other
994concerns (even if it's seemingly compatible with the principles), please express
995your concern.
996
997**Escalate if there's any doubt!**
Ilya Shermanf64bca252020-11-10 23:16:24998
Robert Kaplow6be6fbf2021-04-19 17:30:38999## Clarity
Ilya Shermanf64bca252020-11-10 23:16:241000
1001Is the metadata clear enough for [all Chromies](#Understandable-to-Everyone) to
1002understand what the metric is recording? Consider the histogram name,
1003description, units, enum labels, etc.
1004
1005It's really common for developers to forget to list [when the metric is
1006recorded](#State-When-It-Is-Recorded). This is particularly important context,
1007so please remind developers to clearly document it.
1008
1009Note: Clarity is a bit less important for very niche metrics used only by a
1010couple of engineers. However, it's hard to assess the metric design and
1011correctness if the metadata is especially unclear.
1012
Robert Kaplow6be6fbf2021-04-19 17:30:381013## Metric design
Ilya Shermanf64bca252020-11-10 23:16:241014
1015* Does the metric definition make sense?
1016* Will the resulting data be interpretable at analysis time?
1017
Robert Kaplow6be6fbf2021-04-19 17:30:381018## Correctness
Ilya Shermanf64bca252020-11-10 23:16:241019
1020Is the histogram being recorded correctly?
1021
1022* Does the bucket layout look reasonable?
1023
1024 * The metrics APIs like base::UmaHistogram* have some sharp edges,
1025 especially for the APIs that require specifying the number of
1026 buckets. Check for off-by-one errors and unused buckets.
1027
1028 * Is the bucket layout efficient? Typically, push back if there are >50
1029 buckets -- this can be ok in some cases, but make sure that the CL author
1030 has consciously considered the tradeoffs here and is making a reasonable
1031 choice.
1032
1033 * For timing metrics, do the min and max bounds make sense for the duration
1034 that is being measured?
1035
1036* The base::UmaHistogram* functions are
1037 [generally preferred](#Coding-Emitting-to-Histograms) over the
1038 UMA_HISTOGRAM_* macros. If using the macros, remember that names must be
1039 runtime constants!
1040
1041Also, related to [clarity](#Clarity): Does the client logic correctly implement
1042the metric described in the XML metadata? Some common errors to watch out for:
1043
1044* The metric is only emitted within an if-stmt (e.g., only if some data is
1045 available) and this restriction isn't mentioned in the metadata description.
1046
1047* The metric description states that it's recorded when X happens, but it's
1048 actually recorded when X is scheduled to occur, or only emitted when X
1049 succeeds (but omitted on failure), etc.
1050
1051When the metadata and the client logic do not match, the appropriate solution
1052might be to update the metadata, or it might be to update the client
1053logic. Guide this decision by considering what data will be more easily
1054interpretable and what data will have hidden surprises/gotchas.
1055
Robert Kaplow6be6fbf2021-04-19 17:30:381056## Sustainability
Ilya Shermanf64bca252020-11-10 23:16:241057
Robert Kaplowcd6e0422021-04-07 21:58:531058* Is the CL adding a reasonable number of metrics/buckets?
Ilya Shermanf64bca252020-11-10 23:16:241059 * When reviewing a CL that is trying to add many metrics at once, guide the CL
1060 author toward an appropriate solution for their needs. For example,
1061 multidimensional metrics can be recorded via UKM, and we are currently
Robert Kaplowcd6e0422021-04-07 21:58:531062 building support for structured metrics in UMA.
1063 * There's no hard rule, but anything above 20 separate histograms should be
1064 escalated by being assigned to [email protected].
1065 * Similarly, any histogram with more than 100 possible buckets should be
1066 escalated by being assigned to [email protected].
Ilya Shermanf64bca252020-11-10 23:16:241067
1068* Are expiry dates being set
Victor Hugo Vianna Silvaf27d8387c2024-06-11 14:19:191069 [appropriately](#How-to-choose-expiry-for-new-histograms)?
Ilya Shermanf64bca252020-11-10 23:16:241070
Robert Kaplow6be6fbf2021-04-19 17:30:381071## Everything Else!
Ilya Shermanf64bca252020-11-10 23:16:241072
1073This document describes many other nuances that are important for defining and
1074recording useful metrics. Check CLs for these other types of issues as well.
1075
1076And, as you would with a language style guide, periodically re-review the doc to
1077stay up to date on the details.
1078
Ilya Shermanf64bca252020-11-10 23:16:241079
Robert Kaplow6be6fbf2021-04-19 17:30:381080# Team Documentation
Ilya Shermanf64bca252020-11-10 23:16:241081
Caitlin Fischerb466a042019-07-31 21:41:461082
1083## Processing histograms.xml
1084
1085When working with histograms.xml, verify whether you require fully expanded
1086OWNERS files. Many scripts in this directory process histograms.xml, and
1087sometimes OWNERS file paths are expanded and other times they are not. OWNERS
1088paths are expanded when scripts make use of merge_xml's function MergeFiles;
1089otherwise, they are not.