blob: 9698fc60fa7c7549720db40cd3bd6495c2ab7d08 [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 Pearson4c4bc972018-05-16 20:01:0658## Coding (Emitting to Histograms)
59
Daniel Cheng01cd75932020-02-06 16:43:4560Prefer the helper functions defined in
Mark Pearsoned73f1f2019-03-22 18:00:1261[histogram_functions.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_functions.h).
Daniel Cheng01cd75932020-02-06 16:43:4562These functions take a lock and perform a map lookup, but the overhead is
63generally insignificant. However, when recording metrics on the critical path
64(e.g. called in a loop or logged multiple times per second), use the macros in
65[histogram_macros.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h)
66instead. These macros cache a pointer to the histogram object for efficiency,
67though this comes at the cost of increased binary size: 130 bytes/macro usage
68sounds small but quickly adds up.
Mark Pearson159c38972018-06-05 19:44:0869
Mark Pearson4c4bc972018-05-16 20:01:0670### Don't Use the Same Histogram Logging Call in Multiple Places
71
72These logging macros and functions have long names and sometimes include extra
Caitlin Fischerb5e94352020-10-27 17:34:5073parameters (defining the number of buckets for example). Use a helper function
74if possible. This leads to shorter, more readable code that's also more
75resilient to problems that could be introduced when making changes. (One could,
Mark Pearson4c4bc972018-05-16 20:01:0676for example, erroneously change the bucketing of the histogram in one call but
77not the other.)
78
79### Use Fixed Strings When Using Histogram Macros
80
81When using histogram macros (calls such as `UMA_HISTOGRAM_ENUMERATION`), you're
Victor-Gabriel Savub2afb6f42019-10-23 07:28:2382not allowed to construct your string dynamically so that it can vary at a
Caitlin Fischerb5e94352020-10-27 17:34:5083callsite. At a given callsite (preferably you have only one), the string
84should be the same every time the macro is called. If you need to use dynamic
Mark Pearson74c53212019-03-08 00:34:0885names, use the functions in histogram_functions.h instead of the macros.
Mark Pearson4c4bc972018-05-16 20:01:0686
Arthur Milchiora70d5e62022-08-02 05:10:5687### Don't Use Same Inline String in Multiple Places
Mark Pearson4c4bc972018-05-16 20:01:0688
89If you must use the histogram name in multiple places, use a compile-time
90constant of appropriate scope that can be referenced everywhere. Using inline
91strings in multiple places can lead to errors if you ever need to revise the
Jana Grill81103722023-01-19 16:31:5392name and you update one location and forget another.
Mark Pearson4c4bc972018-05-16 20:01:0693
94### Efficiency
95
Mark Pearsoned73f1f2019-03-22 18:00:1296Generally, don't be concerned about the processing cost of emitting to a
97histogram (unless you're using [sparse
98histograms](#When-To-Use-Sparse-Histograms)). The normal histogram code is
99highly optimized. If you are recording to a histogram in particularly
100performance-sensitive or "hot" code, make sure you're using the histogram
101macros; see [reasons above](#Coding-Emitting-to-Histograms).
Mark Pearson4c4bc972018-05-16 20:01:06102
103## Picking Your Histogram Type
mpearson2b5f7e02016-10-03 21:27:03104
mpearson2b5f7e02016-10-03 21:27:03105### Enum Histograms
106
107Enumerated histogram are most appropriate when you have a list of connected /
Caitlin Fischerb5e94352020-10-27 17:34:50108related states that should be analyzed jointly. For example, the set of actions
109that can be done on the New Tab Page (use the omnibox, click a most visited
110tile, click a bookmark, etc.) would make a good enumerated histogram.
mpearson2b5f7e02016-10-03 21:27:03111If the total count of your histogram (i.e. the sum across all buckets) is
Caitlin Fischerb5e94352020-10-27 17:34:50112something meaningful—as it is in this example—that is generally a good sign.
mpearson2b5f7e02016-10-03 21:27:03113However, the total count does not have to be meaningful for an enum histogram
114to still be the right choice.
115
Caitlin Fischerb5e94352020-10-27 17:34:50116Enumerated histograms are also appropriate for counting events. Use a simple
Ilya Shermanb9641892020-11-06 00:53:55117boolean histogram. It's usually best if you have a comparison point in the same
Caitlin Fischerb5e94352020-10-27 17:34:50118histogram. For example, if you want to count pages opened from the history page,
119it might be a useful comparison to have the same histogram record the number of
120times the history page was opened.
Mark Pearsona768d0222019-03-20 02:16:00121
Ilya Shermanb9641892020-11-06 00:53:55122In rarer cases, it's okay if you only log to one bucket (say, `true`). However,
123think about whether this will provide enough [context](#Provide-Context). For
124example, suppose we want to understand how often users interact with a button.
Jared Saul73a9daaf2021-05-04 15:33:02125Just knowing that users clicked this particular button 1 million times in a day
Ilya Shermanb9641892020-11-06 00:53:55126is not very informative on its own: The size of Chrome's user base is constantly
127changing, only a subset of users have consented to metrics reporting, different
128platforms have different sampling rates for metrics reporting, and so on. The
129data would be much easier to make sense of if it included a baseline: how often
130is the button shown?
131
Mark Pearson07356b042024-05-16 20:06:08132There is another problem with using another histogram as a comparison point.
133Google systems for processing UMA data attempt to exclude data that this is
134deemed unreliable or somehow anomalous. It's possible that it may exclude data
135from a client for one histogram and not exclude data from that client for the
136other.
137
Caitlin Fischerb5e94352020-10-27 17:34:50138If only a few buckets are emitted to, consider using a [sparse
Mark Pearson4d0b4632017-10-04 21:58:48139histogram](#When-To-Use-Sparse-Histograms).
140
Daniel Cheng914170d22019-05-08 09:46:32141#### Requirements
142
143Enums logged in histograms must:
144
145- be prefixed with the comment:
146 ```c++
147 // These values are persisted to logs. Entries should not be renumbered and
148 // numeric values should never be reused.
149 ```
150- be numbered starting from `0`. Note this bullet point does *not* apply for
151 enums logged with sparse histograms.
Caitlin Fischerb5e94352020-10-27 17:34:50152- have enumerators with explicit values (`= 0`, `= 1`, `= 2`) to make it clear
Daniel Cheng914170d22019-05-08 09:46:32153 that the actual values are important. This also makes it easy to match the
154 values between the C++/Java definition and [histograms.xml](./histograms.xml).
155- not renumber or reuse enumerator values. When adding a new enumerator, append
156 the new enumerator to the end. When removing an unused enumerator, comment it
157 out, making it clear the value was previously used.
158
159If your enum histogram has a catch-all / miscellaneous bucket, put that bucket
Caitlin Fischerb5e94352020-10-27 17:34:50160first (`= 0`). This makes the bucket easy to find on the dashboard if additional
161buckets are added later.
Daniel Cheng914170d22019-05-08 09:46:32162
163#### Usage
164
Ilya Shermanb6bd3c72020-04-15 23:08:15165*In C++*, define an `enum class` with a `kMaxValue` enumerator:
Daniel Cheng914170d22019-05-08 09:46:32166
Steven Holteecf841d2018-08-10 00:53:34167```c++
Hong Xu4b0bc44f2023-08-01 20:30:42168// These values are persisted to logs. Entries should not be renumbered and
169// numeric values should never be reused.
James Lee53e80dc2024-04-19 11:31:06170//
171// LINT.IfChange(NewTabPageAction)
Daniel Chengcda1df5b2018-03-30 21:30:16172enum class NewTabPageAction {
173 kUseOmnibox = 0,
174 kClickTitle = 1,
Daniel Cheng914170d22019-05-08 09:46:32175 // kUseSearchbox = 2, // no longer used, combined into omnibox
176 kOpenBookmark = 3,
Daniel Chengcda1df5b2018-03-30 21:30:16177 kMaxValue = kOpenBookmark,
178};
James Lee53e80dc2024-04-19 11:31:06179// LINT.ThenChange(//path/to/enums.xml:NewTabPageActionEnum)
Daniel Chengcda1df5b2018-03-30 21:30:16180```
Daniel Chengcda1df5b2018-03-30 21:30:16181
James Lee53e80dc2024-04-19 11:31:06182The `LINT.IfChange / LINT.ThenChange` comments point between the code and XML
183definitions of the enum, to encourage them to be kept in sync. See
184[guide](https://www.chromium.org/chromium-os/developer-library/guides/development/keep-files-in-sync/)
185and [more details](http://go/gerrit-ifthisthenthat).
186
Daniel Cheng914170d22019-05-08 09:46:32187`kMaxValue` is a special enumerator that must share the highest enumerator
188value, typically done by aliasing it with the enumerator with the highest
189value: clang automatically checks that `kMaxValue` is correctly set for `enum
190class`.
191
Takashi Toyoshima0b520762024-05-08 23:17:33192*In Mojo*, define an `enum` without a `kMaxValue` enumerator as `kMaxValue` is
193autogenerated for Mojo C++ bindings:
194
195```c++
196// These values are persisted to logs. Entries should not be renumbered and
197// numeric values should never be reused.
198//
199// LINT.IfChange(PreloadType)
200enum PrerenderType {
201 kPrefetch = 0,
202 // kPrerender = 1, // deprecated, revamped as kPrerender2
203 kNoStatePrefetch = 2,
204 kPrerender2 = 3,
205};
206// LINT.ThenChange(//path/to/enums.xml:PreloadType)
207```
208
209*In C++*, the histogram helpers use the `kMaxValue` convention, and the enum may
210be logged with:
Daniel Cheng914170d22019-05-08 09:46:32211
212```c++
Daniel Chengcda1df5b2018-03-30 21:30:16213UMA_HISTOGRAM_ENUMERATION("NewTabPageAction", action);
214```
Daniel Chengcda1df5b2018-03-30 21:30:16215
Daniel Cheng914170d22019-05-08 09:46:32216or:
217
Steven Holteecf841d2018-08-10 00:53:34218```c++
Daniel Cheng914170d22019-05-08 09:46:32219UmaHistogramEnumeration("NewTabPageAction", action);
Daniel Chengcda1df5b2018-03-30 21:30:16220```
Steven Holteecf841d2018-08-10 00:53:34221
Hong Xu365a4f72022-02-25 04:26:02222where `action` is an enumerator of the enumeration type `NewTabPageAction`.
223
Nate Fischer1f6efe52020-06-17 19:18:21224Logging histograms from Java should look similar:
225
226```java
227// These values are persisted to logs. Entries should not be renumbered and
228// numeric values should never be reused.
229@IntDef({NewTabPageAction.USE_OMNIBOX, NewTabPageAction.CLICK_TITLE,
230 NewTabPageAction.OPEN_BOOKMARK})
231private @interface NewTabPageAction {
232 int USE_OMNIBOX = 0;
233 int CLICK_TITLE = 1;
234 // int USE_SEARCHBOX = 2; // no longer used, combined into omnibox
235 int OPEN_BOOKMARK = 3;
236 int COUNT = 4;
237}
238
239// Using a helper function is optional, but avoids some boilerplate.
240private static void logNewTabPageAction(@NewTabPageAction int action) {
241 RecordHistogram.recordEnumeratedHistogram(
242 "NewTabPageAction", action, NewTabPageAction.COUNT);
243}
244```
245
Hong Xu77292842022-05-18 06:43:59246Finally, regardless of the programming language you are using, add the
James Lee53e80dc2024-04-19 11:31:06247definition of the enumerator to [enums.xml](./enums.xml), and add linter checks
248to keep the C++/Java and XML values in sync:
249
250```xml
251<!-- LINT.IfChange(NewTabPageActionEnum) -->
252<enum name="NewTabPageActionEnum">
253 ...
254</enum>
255<!-- LINT.ThenChange(//path/to/cpp_definition.h:NewTabPageAction) -->
256```
Hong Xu77292842022-05-18 06:43:59257
Daniel Cheng914170d22019-05-08 09:46:32258#### Legacy Enums
259
260**Note: this method of defining histogram enums is deprecated. Do not use this
Ilya Shermanb6bd3c72020-04-15 23:08:15261for new enums *in C++*.**
Daniel Cheng914170d22019-05-08 09:46:32262
Chris Blumebdca7ca2020-06-08 15:48:35263Many legacy enums define a `kCount` sentinel, relying on the compiler to
Daniel Cheng914170d22019-05-08 09:46:32264automatically update it when new entries are added:
265
Steven Holteecf841d2018-08-10 00:53:34266```c++
Daniel Chengcda1df5b2018-03-30 21:30:16267enum class NewTabPageAction {
268 kUseOmnibox = 0,
269 kClickTitle = 1,
Daniel Cheng914170d22019-05-08 09:46:32270 // kUseSearchbox = 2, // no longer used, combined into omnibox
271 kOpenBookmark = 3,
Daniel Chengcda1df5b2018-03-30 21:30:16272 kCount,
273};
Daniel Cheng914170d22019-05-08 09:46:32274```
Steven Holteecf841d2018-08-10 00:53:34275
Daniel Cheng914170d22019-05-08 09:46:32276These enums must be recorded using the legacy helpers:
277
278```c++
Daniel Chengcda1df5b2018-03-30 21:30:16279UMA_HISTOGRAM_ENUMERATION("NewTabPageAction", action, NewTabPageAction::kCount);
280```
281
Daniel Cheng914170d22019-05-08 09:46:32282or:
283
284```c++
285UmaHistogramEnumeration("NewTabPageAction", action, NewTabPageAction::kCount);
286```
mpearsonb36013be2017-02-10 20:10:54287
Matt Giucaf3e0e2532017-10-03 23:07:52288### Flag Histograms
289
290When adding a new flag in
291[about_flags.cc](../../../chrome/browser/about_flags.cc), you need to add a
Caitlin Fischerb5e94352020-10-27 17:34:50292corresponding entry to [enums.xml](./enums.xml). This is automatically verified
293by the `AboutFlagsHistogramTest` unit test.
Matt Giucaf3e0e2532017-10-03 23:07:52294
295To add a new entry:
296
manukh26fe9852022-10-04 23:38:142971. After adding flags
298 to [about_flags.cc](../../../chrome/browser/about_flags.cc),
299 run `generate_flag_enums.py --feature <your awesome feature>` or
300 simply `generate_flag_enums.py` (slower).
301
302You can alternatively follow these steps:
303
Matt Giucaf3e0e2532017-10-03 23:07:523041. Edit [enums.xml](./enums.xml), adding the feature to the `LoginCustomFlags`
Brett Wilsonf4d58772017-10-30 21:37:57305 enum section, with any unique value (just make one up, although whatever it
Caitlin Fischerb5e94352020-10-27 17:34:50306 is needs to appear in sorted order; `pretty_print.py` can do this for you).
Matt Giucaf3e0e2532017-10-03 23:07:523072. Build `unit_tests`, then run `unit_tests
Eric Lawrenced4d7d5c2023-05-09 20:48:25308 --gtest_filter=AboutFlagsHistogramTest.*` to compute the correct value.
Matt Giucaf3e0e2532017-10-03 23:07:523093. Update the entry in [enums.xml](./enums.xml) with the correct value, and move
Caitlin Fischerb5e94352020-10-27 17:34:50310 it so the list is sorted by value (`pretty_print.py` can do this for you).
Matt Giucaf3e0e2532017-10-03 23:07:523114. Re-run the test to ensure the value and ordering are correct.
312
313You can also use `tools/metrics/histograms/validate_format.py` to check the
314ordering (but not that the value is correct).
315
316Don't remove entries when removing a flag; they are still used to decode data
317from previous Chrome versions.
318
mpearson2b5f7e02016-10-03 21:27:03319### Count Histograms
320
321[histogram_macros.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h)
Caitlin Fischerfc138c82021-11-04 21:31:19322provides macros for some common count types, such as memory or elapsed time, in
Caitlin Fischerb5e94352020-10-27 17:34:50323addition to general count macros. These have reasonable default values; you
324seldom need to choose the number of buckets or histogram min. However, you still
325need to choose the histogram max (use the advice below).
mpearson2b5f7e02016-10-03 21:27:03326
Caitlin Fischerfc138c82021-11-04 21:31:19327If none of the default macros work well for you, please thoughtfully choose a
328min, max, and bucket count for your histogram using the advice below.
mpearson2b5f7e02016-10-03 21:27:03329
rkaplow6dfcb892016-10-04 14:04:27330#### Count Histograms: Choosing Min and Max
mpearson2b5f7e02016-10-03 21:27:03331
Caitlin Fischerfc138c82021-11-04 21:31:19332For the max, choose a value such that very few histogram samples exceed the max.
333If a sample is greater than or equal to the max value, it is put in an
334"overflow" bucket. If this bucket is too large, it can be difficult to compute
335statistics. One rule of thumb is that at most 1% of samples should be in the
Robert Kaplowcbc6fd62021-03-19 15:11:40336overflow bucket (and ideally, less). This allows analysis of the 99th
337percentile. Err on the side of too large a range versus too short a range.
Caitlin Fischerfc138c82021-11-04 21:31:19338Remember that if you choose poorly, you'll have to wait for another release
339cycle to fix it.
mpearson2b5f7e02016-10-03 21:27:03340
Caitlin Fischerfc138c82021-11-04 21:31:19341For the min, use 1 if you care about all possible values (zero and above). All
342histograms have an underflow bucket for emitted zeros, so a min of 1 is
343appropriate. Otherwise, choose the min appropriate for your particular
344situation.
mpearson2b5f7e02016-10-03 21:27:03345
rkaplow6dfcb892016-10-04 14:04:27346#### Count Histograms: Choosing Number of Buckets
mpearson2b5f7e02016-10-03 21:27:03347
Caitlin Fischerb5e94352020-10-27 17:34:50348Choose the smallest number of buckets that give you the granularity you need. By
Hong Xu3a229d832022-05-12 04:37:30349default, count histogram bucket sizes increase exponentially with respect to the
350value (i.e., exponential binning), so you can get fine granularity when the
351values are small yet still reasonable resolution when the values are larger. The
352macros default to 50 buckets (or 100 buckets for histograms with wide ranges),
353which is appropriate for most purposes. Because histograms pre-allocate all the
354buckets, the number of buckets selected directly dictates how much memory is
355used. Do not exceed 100 buckets without good reason (and consider whether
356[sparse histograms](#When-To-Use-Sparse-Histograms) might work better for you in
357that case—they do not pre-allocate their buckets).
rkaplow8a62ef62016-10-06 14:42:34358
Mark Pearson6be2f35c2018-08-14 07:06:02359### Timing Histograms
360
Yoshisato Yanagisawa4782e2f2024-04-19 00:50:34361You can easily emit a time duration (time delta) using base::UmaHistogramTimes,
362base::UmaHistogramMediumTimes, base::UmaHistogramLongTimes, and their friends.
363For the critical path, UMA_HISTOGRAM_TIMES, UMA_HISTOGRAM_MEDIUM_TIMES,
364UMA_HISTOGRAM_LONG_TIMES macros, and their friends, as well as helpers like
365SCOPED_UMA_HISTOGRAM_TIMER are also available. Many timing
Mark Pearson6be2f35c2018-08-14 07:06:02366histograms are used for performance monitoring; if this is the case for you,
367please read [this document about how to structure timing histograms to make
368them more useful and
Paul Jensen5107d9c2018-10-22 22:24:06369actionable](https://chromium.googlesource.com/chromium/src/+/lkgr/docs/speed/diagnostic_metrics.md).
Mark Pearson6be2f35c2018-08-14 07:06:02370
Mark Pearson49928ec2018-06-05 20:15:49371### Percentage or Ratio Histograms
372
Caitlin Fischerb5e94352020-10-27 17:34:50373You can easily emit a percentage histogram using the UMA_HISTOGRAM_PERCENTAGE
374macro provided in
Mark Pearson49928ec2018-06-05 20:15:49375[histogram_macros.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h).
Caitlin Fischerb5e94352020-10-27 17:34:50376You can also easily emit any ratio as a linear histogram (for equally sized
377buckets).
Mark Pearson49928ec2018-06-05 20:15:49378
Caitlin Fischerb5e94352020-10-27 17:34:50379For such histograms, you want each value recorded to cover approximately the
380same span of time. This typically means emitting values periodically at a set
381time interval, such as every 5 minutes. We do not recommend recording a ratio at
382the end of a video playback, as video lengths vary greatly.
Mark Pearson49928ec2018-06-05 20:15:49383
Mark Pearson9be8bffa2020-03-03 19:08:02384It is okay to emit at the end of an animation sequence when what's being
Caitlin Fischerb5e94352020-10-27 17:34:50385animated is fixed / known. In this case, each value represents roughly the same
386span of time.
Mark Pearson9be8bffa2020-03-03 19:08:02387
Caitlin Fischerb5e94352020-10-27 17:34:50388Why? You typically cannot make decisions based on histograms whose values are
389recorded in response to an event that varies in length because such metrics can
390conflate heavy usage with light usage. It's easier to reason about metrics that
391avoid this source of bias.
Mark Pearson49928ec2018-06-05 20:15:49392
Caitlin Fischerb5e94352020-10-27 17:34:50393Many developers have been bitten by this. For example, it was previously common
394to emit an actions-per-minute ratio whenever Chrome was backgrounded. Precisely,
395these metrics computed the number of uses of a particular action during a Chrome
396session, divided by length of time Chrome had been open. Sometimes, the recorded
397rate was based on a short interaction with Chrome–a few seconds or a minute.
398Other times, the recorded rate was based on a long interaction, tens of minutes
399or hours. These two situations are indistinguishable in the UMA logs–the
400recorded values can be identical.
Mark Pearson49928ec2018-06-05 20:15:49401
Caitlin Fischerb5e94352020-10-27 17:34:50402The inability to distinguish these two qualitatively different settings make
403such histograms effectively uninterpretable and not actionable. Emitting at a
404regular interval avoids the issue. Each value represents the same amount of time
405(e.g., one minute of video playback).
Mark Pearson49928ec2018-06-05 20:15:49406
rkaplow8a62ef62016-10-06 14:42:34407### Local Histograms
408
Gayane Petrosyana6ee443c2018-05-17 21:39:54409Histograms can be added via [Local macros](https://codesearch.chromium.org/chromium/src/base/metrics/histogram_macros_local.h).
Caitlin Fischerb5e94352020-10-27 17:34:50410These still record locally, but are not uploaded to UMA and are therefore not
411available for analysis. This can be useful for metrics only needed for local
412debugging. We don't recommend using local histograms outside of that scenario.
rkaplow8a62ef62016-10-06 14:42:34413
414### Multidimensional Histograms
415
Caitlin Fischerb5e94352020-10-27 17:34:50416It is common to be interested in logging multidimensional data–where multiple
rkaplow8a62ef62016-10-06 14:42:34417pieces of information need to be logged together. For example, a developer may
418be interested in the counts of features X and Y based on whether a user is in
419state A or B. In this case, they want to know the count of X under state A,
420as well as the other three permutations.
421
422There is no general purpose solution for this type of analysis. We suggest
423using the workaround of using an enum of length MxN, where you log each unique
424pair {state, feature} as a separate entry in the same enum. If this causes a
Gayane Petrosyana6ee443c2018-05-17 21:39:54425large explosion in data (i.e. >100 enum entries), a [sparse histogram](#When-To-Use-Sparse-Histograms)
Caitlin Fischerb5e94352020-10-27 17:34:50426may be appropriate. If you are unsure of the best way to proceed, please contact
427someone from the OWNERS file.
Gayane Petrosyana6ee443c2018-05-17 21:39:54428
429## Histogram Expiry
430
Caitlin Fischerb5e94352020-10-27 17:34:50431Histogram expiry is specified by the `expires_after` attribute in histogram
Mark Pearson37c3c9a2023-06-29 17:17:30432descriptions in histograms.xml. It is a required attribute. The attribute can
433be specified as date in **YYYY-MM-DD** format or as Chrome milestone in
434**M**\*(e.g. M105) format. In the latter case, the actual expiry date is about
43512 weeks after that branch is cut, or basically when it is replaced on the
436"stable" channel by the following release.
Brian Whitefa0a3fa2019-05-13 16:58:11437
Mark Pearsonce4371c2021-03-15 23:57:42438After a histogram expires, it ceases to be displayed on the dashboard.
439Follow [these directions](#extending) to extend it.
Brian Whitefa0a3fa2019-05-13 16:58:11440
Caitlin Fischerb5e94352020-10-27 17:34:50441Once a histogram has expired, the code that records it becomes dead code and
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33442should be removed from the codebase. You should also [clean up](#obsolete) the
Alexei Svitkined4cbf402022-11-14 20:55:25443corresponding entry in histograms.xml. In _rare_ cases, a histogram may be
444expired intentionally while keeping the code around; such cases must be
Alexei Svitkine6fbe8ac2022-11-14 21:17:40445[annotated appropriately](#Intentionally-expired-histograms) in histograms.xml.
Gayane Petrosyana6ee443c2018-05-17 21:39:54446
Brian White8614f812019-02-07 21:07:01447In **rare** cases, the expiry can be set to "never". This is used to denote
Robert Kaplowcbc6fd62021-03-19 15:11:40448metrics of critical importance that are, typically, used for other reports. For
449example, all metrics of the
450"[heartbeat](https://uma.googleplex.com/p/chrome/variations)" are set to never
451expire. All metrics that never expire must have an XML comment describing why so
452that it can be audited in the future. Setting an expiry to "never" must be
453reviewed by [email protected].
Brian White8614f812019-02-07 21:07:01454
455```
456<!-- expires-never: "heartbeat" metric (internal: go/uma-heartbeats) -->
457```
458
Mark Pearson37c3c9a2023-06-29 17:17:30459It is never appropriate to set the expiry to "never" on a new histogram. Most
460new histograms don't turn out to have the properties the implementer wants,
461whether due to bugs in the implementation or simply an evolving understanding
462of what should be measured.
Gayane Petrosyana6ee443c2018-05-17 21:39:54463
Yoshisato Yanagisawa19d35ca2024-04-09 03:50:18464#### Guidelines on expiry
Gayane Petrosyana6ee443c2018-05-17 21:39:54465
Ilya Sherman67418ea2019-11-27 01:28:23466Here are some guidelines for common scenarios:
Gayane Petrosyana6ee443c2018-05-17 21:39:54467
Yoshisato Yanagisawa19d35ca2024-04-09 03:50:18468* If the listed owner moved to a different project, find a new owner.
Ilya Sherman67418ea2019-11-27 01:28:23469* If neither the owner nor the team uses the histogram, remove it.
470* If the histogram is not in use now, but might be useful in the far future,
471 remove it.
472* If the histogram is not in use now, but might be useful in the near
Brian Whitedb68067b2021-10-13 18:27:28473 future, pick ~3 months (also ~3 milestones) ahead.
Yoshisato Yanagisawa19d35ca2024-04-09 03:50:18474* Otherwise, pick an expiry that is reasonable for how long the metric should
475 be used, up to a year.
Ilya Sherman67418ea2019-11-27 01:28:23476
Brian Whitedb68067b2021-10-13 18:27:28477We also have a tool that automatically extends expiry dates. The most frequently
478accessed histograms, currently 99%, have their expirations automatically
479extended every Tuesday to 6 months from the date of the run. Googlers can view
480the [design
481doc](https://docs.google.com/document/d/1IEAeBF9UnYQMDfyh2gdvE7WlUKsfIXIZUw7qNoU89A4)
482of the program that does this. The bottom line is: If the histogram is being
483checked, it should be extended without developer interaction.
Gayane Petrosyana6ee443c2018-05-17 21:39:54484
Yoshisato Yanagisawa19d35ca2024-04-09 03:50:18485#### How to choose expiry for new histograms
486
487In general, set an expiry that is reasonable for how long the metric should
488be used, up to a year.
489
490Some common cases:
491
492* When adding a histogram to evaluate a feature launch, set an expiry date
493 consistent with the expected feature launch date.
494* If you expect the histogram to be useful for an indefinite time, set an
495 expiry date up to 1 year out. This gives a chance to re-evaluate whether
496 the histogram indeed proved to be useful.
497* Otherwise, 3-6 months (3-6 milestones) is typically a good choice.
498
Mark Pearsonce4371c2021-03-15 23:57:42499#### How to extend an expired histogram {#extending}
500
501You can revive an expired histogram by setting the expiration date to a
502date in the future.
503
504There's some leeway here. A client may continue to send data for that
505histogram for some time after the official expiry date so simply bumping
506the 'expires_after' date at HEAD may be sufficient to resurrect it without
507any data discontinuity.
508
509If a histogram expired more than a month ago (for histograms with an
510expiration date) or more than one milestone ago (for histograms with
511expiration milestones; this means top-of-tree is two or more milestones away
512from expired milestone), then you may be outside the safety window. In this
513case, when extending the histogram add to the histogram description a
514message: "Warning: this histogram was expired from DATE to DATE; data may be
515missing." (For milestones, write something similar.)
516
517When reviving a histogram outside the safety window, realize the change to
518histograms.xml to revive it rolls out with the binary release. It takes
519some time to get to the stable channel.
520
521It you need to revive it faster, the histogram can be re-enabled via adding to
522the [expired histogram allowlist](#Expired-histogram-allowlist).
523
Gayane Petrosyana6ee443c2018-05-17 21:39:54524### Expired histogram notifier
525
Caitlin Fischerb5e94352020-10-27 17:34:50526The expired histogram notifier notifies histogram owners before their histograms
527expire by creating crbugs, which are assigned to owners. This allows owners to
528extend the lifetime of their histograms, if needed, or deprecate them. The
529notifier regularly checks all histograms across the histograms.xml files and
530identifies expired or soon-to-be expired histograms. It then creates or updates
531crbugs accordingly.
Gayane Petrosyana6ee443c2018-05-17 21:39:54532
Caitlin Fischer9f4841052020-11-04 21:02:44533### Expired histogram allowlist
Gayane Petrosyana6ee443c2018-05-17 21:39:54534
Caitlin Fischerb5e94352020-10-27 17:34:50535If a histogram expires but turns out to be useful, you can add the histogram's
Alexei Svitkined4cbf402022-11-14 20:55:25536name to the allowlist to re-enable logging for it, until the updated expiration
537date reaches the Stable channel. When doing so, update the histogram's summary
538to document the period during which the histogram's data is incomplete. To add a
539histogram to the allowlist, see the internal documentation:
Caitlin Fischerb5e94352020-10-27 17:34:50540[Histogram Expiry](https://goto.google.com/histogram-expiry-gdoc).
mpearson2b5f7e02016-10-03 21:27:03541
Alexei Svitkine6fbe8ac2022-11-14 21:17:40542### Intentionally expired histograms
Alexei Svitkined4cbf402022-11-14 20:55:25543
544In **rare** cases, a histogram may be expired intentionally while keeping the
545code around. For example, this can be useful for diagnostic metrics that are
546occasionally needed to investigate specific bugs, but do not need to be reported
547otherwise.
548
549To avoid such histograms to be flagged for code clean up, they must be annotated
550in the histograms.xml with the `expired_intentionally` tag as follows:
551
552```xml
553<histogram name="Tab.Open" enum="TabType" expires_after="M100">
554 <expired_intentionally>Kept as a diagnostic metric.</expired_intentionally>
555 <owner>[email protected]</owner>
556 <summary>Histogram summary.</summary>
557</histogram>
558```
559
mpearson72a5c91392017-05-09 22:49:44560## Testing
mpearson2b5f7e02016-10-03 21:27:03561
Caitlin Fischerb5e94352020-10-27 17:34:50562Test your histograms using `chrome://histograms`. Make sure they're being
rkaplow6dfcb892016-10-04 14:04:27563emitted to when you expect and not emitted to at other times. Also check that
Caitlin Fischerb5e94352020-10-27 17:34:50564the values emitted to are correct. Finally, for count histograms, make sure
rkaplow6dfcb892016-10-04 14:04:27565that buckets capture enough precision for your needs over the range.
mpearson2b5f7e02016-10-03 21:27:03566
Ivan Sandrk8ffc5832018-07-09 12:34:58567Pro tip: You can filter the set of histograms shown on `chrome://histograms` by
Luc Nguyenb1324cb2022-12-17 16:23:41568appending to the URL. For example, `chrome://histograms/UserActions` shows
569only histograms whose names contain "UserActions", such as
570"UMA.UserActionsCount".
Ivan Sandrk8ffc5832018-07-09 12:34:58571
mpearson72a5c91392017-05-09 22:49:44572In addition to testing interactively, you can have unit tests examine the
Caitlin Fischerb5e94352020-10-27 17:34:50573values emitted to histograms. See [histogram_tester.h](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_tester.h)
mpearson72a5c91392017-05-09 22:49:44574for details.
mpearson2b5f7e02016-10-03 21:27:03575
Luc Nguyenb1324cb2022-12-17 16:23:41576See also `chrome://metrics-internals` ([docs](https://chromium.googlesource.com/chromium/src/+/master/components/metrics/debug/README.md))
577for more thorough manual testing if needed.
578
Robert Kaplow82027632023-02-13 16:31:52579By default, histograms in unit or browser tests will not be actually uploaded.
580In general, you can rely on the UMA infrastructure to upload the metrics correctly.
581
Alan Screen291bc9a2023-06-27 21:16:49582### Don't Use Histograms to Prove Main Logic Correctness
583
584Do not rely upon using histograms in tests as a way to prove correctness of
585your main program logic. If a unit or browser test uses a histogram count as a
586way to validate logic then that test coverage would be lost if the histogram is
587deleted after it has expired. That situation would prevent cleanup of the
588histogram. Construct your tests using other means to validate your general
589logic, and only use
590[`HistogramTester`](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_tester.h)
591to verify that the histogram values are being generated as you would expect.
592
Dana Friedac15ff82024-04-02 21:19:34593### Verify Enum and Variant Values
594
595If you have <enum> or <variant> entries that need to be updated to match code,
596you can use
597[HistogramEnumReader](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_enum_reader.h)
598or
599[HistogramVariantsReader](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_enum_reader.h)
600to read and verify the expected values in a unit test. This prevents a mismatch
601between code and histogram data from slipping through CQ.
602
603For an example, see
604[BrowserUserEducationServiceTest.CheckFeaturePromoHistograms](https://cs.chromium.org/chromium/src/chrome/browser/ui/views/user_education/browser_user_education_service_unittest.cc).
605
Mark Pearson4c4bc972018-05-16 20:01:06606## Interpreting the Resulting Data
607
608The top of [go/uma-guide](http://go/uma-guide) has good advice on how to go
Caitlin Fischerb5e94352020-10-27 17:34:50609about analyzing and interpreting the results of UMA data uploaded by users. If
Mark Pearson4c4bc972018-05-16 20:01:06610you're reading this page, you've probably just finished adding a histogram to
611the Chromium source code and you're waiting for users to update their version of
Caitlin Fischerb5e94352020-10-27 17:34:50612Chrome to a version that includes your code. In this case, the best advice is
613to remind you that users who update frequently / quickly are biased. Best take
Mark Pearson4c4bc972018-05-16 20:01:06614the initial statistics with a grain of salt; they're probably *mostly* right but
615not entirely so.
616
mpearson72a5c91392017-05-09 22:49:44617## Revising Histograms
618
Robert Kaplowcbc6fd62021-03-19 15:11:40619When changing the semantics of a histogram (when it's emitted, what the buckets
620represent, the bucket range or number of buckets, etc.), create a new histogram
621with a new name. Otherwise analysis that mixes the data pre- and post- change
622may be misleading. If the histogram name is still the best name choice, the
623recommendation is to simply append a '2' to the name. See [Cleaning Up Histogram
Austin Sullivan1040ce22022-04-13 15:51:29624Entries](#obsolete) for details on how to handle the XML changes.
mpearson2b5f7e02016-10-03 21:27:03625
mpearson72a5c91392017-05-09 22:49:44626## Deleting Histograms
mpearson2b5f7e02016-10-03 21:27:03627
Caitlin Fischerb5e94352020-10-27 17:34:50628Please delete code that emits to histograms that are no longer needed.
629Histograms take up memory. Cleaning up histograms that you no longer care
630about is good! But see the note below on
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33631[Cleaning Up Histogram Entries](#obsolete).
mpearson2b5f7e02016-10-03 21:27:03632
633## Documenting Histograms
634
Darren Shenda91dc752023-03-01 05:28:30635Document histograms in an appropriate [metadata/foo/histograms.xml](https://source.chromium.org/search?q=f:metadata%2F.*%2Fhistograms.xml&ss=chromium%2Fchromium%2Fsrc)
636file.
637
638There is also a [google-internal version of the file](https://goto.google.com/chrome-histograms-internal)
639for two cases:
640
641* The histogram is confidential (an accurate description about how to interpret
642 the histogram would reveal information about Google's plans). In this case,
643 you must only document the histogram in the internal version.
644* The corresponding code that emits the histogram is internal (added only to
645 Chrome code, not to Chromium code). In this case, you may document the
646 histogram in either the internal or external version.
Mark Pearson159c38972018-06-05 19:44:08647
mpearson2b5f7e02016-10-03 21:27:03648### Add Histogram and Documentation in the Same Changelist
649
vapier52b9aba2016-12-14 06:09:25650If possible, please add the [histograms.xml](./histograms.xml) description in
Caitlin Fischerb5e94352020-10-27 17:34:50651the same changelist in which you add the histogram-emitting code. This has
652several benefits. One, it sometimes happens that the
vapier52b9aba2016-12-14 06:09:25653[histograms.xml](./histograms.xml) reviewer has questions or concerns about the
654histogram description that reveal problems with interpretation of the data and
Caitlin Fischerb5e94352020-10-27 17:34:50655call for a different recording strategy. Two, it allows the histogram reviewer
vapier52b9aba2016-12-14 06:09:25656to easily review the emission code to see if it comports with these best
Caitlin Fischerb5e94352020-10-27 17:34:50657practices and to look for other errors.
mpearson2b5f7e02016-10-03 21:27:03658
659### Understandable to Everyone
660
661Histogram descriptions should be roughly understandable to someone not familiar
Caitlin Fischerb5e94352020-10-27 17:34:50662with your feature. Please add a sentence or two of background if necessary.
mpearson2b5f7e02016-10-03 21:27:03663
Robert Kaplowcbc6fd62021-03-19 15:11:40664Note any caveats associated with your histogram in the summary. For example, if
665the set of supported platforms is surprising, such as if a desktop feature is
666not available on Mac, the summary should explain where it is recorded. It is
667also common to have caveats along the lines of "this histogram is only recorded
668if X" (e.g., upon a successful connection to a service, a feature is enabled by
669the user).
670
mpearson2b5f7e02016-10-03 21:27:03671
672### State When It Is Recorded
673
674Histogram descriptions should clearly state when the histogram is emitted
675(profile open? network request received? etc.).
676
Mark Pearsond8fc9fd22021-03-12 20:18:58677Some histograms record error conditions. These should be clear about whether
678all errors are recorded or only the first. If only the first, the histogram
679description should have text like:
680```
681In the case of multiple errors, only the first reason encountered is recorded. Refer
682to Class::FunctionImplementingLogic() for details.
683```
684
Ilya Sherman470c95a2020-09-21 23:05:43685### Provide Clear Units or Enum Labels
686
687For enumerated histograms, including boolean and sparse histograms, provide an
688`enum=` attribute mapping enum values to semantically contentful labels. Define
689the `<enum>` in enums.xml if none of the existing enums are a good fit. Use
690labels whenever they would be clearer than raw numeric values.
691
692For non-enumerated histograms, include a `units=` attribute. Be specific:
693e.g. distinguish "MB" vs. "MiB", refine generic labels like "counts" to more
694precise labels like "pages", etc.
695
jsbellda3a66c2017-02-09 21:40:32696### Owners
rkaplow8a62ef62016-10-06 14:42:34697
Caitlin Fischer254a12f72019-07-31 20:57:03698Histograms need owners, who are the experts on the metric and the points of
699contact for any questions or maintenance tasks, such as extending a histogram's
700expiry or deprecating the metric.
rkaplow8a62ef62016-10-06 14:42:34701
Caitlin Fischer254a12f72019-07-31 20:57:03702Histograms must have a primary owner and may have secondary owners. A primary
Mario Bianucci9947bbd2020-10-28 17:41:47703owner is a Googler with an @google.com or @chromium.org email address, e.g.
Caitlin Fischerb5e94352020-10-27 17:34:50704<owner>[email protected]</owner>, who is ultimately responsible for maintaining
705the metric. Secondary owners may be other individuals, team mailing lists, e.g.
706<owner>[email protected]</owner>, or paths to OWNERS files, e.g.
707<owner>src/directory/OWNERS</owner>.
Mark Pearson74c53212019-03-08 00:34:08708
Caitlin Fischer254a12f72019-07-31 20:57:03709It's a best practice to list multiple owners, so that there's no single point
710of failure for histogram-related questions and maintenance tasks. If you are
711using a metric heavily and understand it intimately, feel free to add yourself
Caitlin Fischerb5e94352020-10-27 17:34:50712as an owner.
Mark Pearson74c53212019-03-08 00:34:08713
Caitlin Fischer254a12f72019-07-31 20:57:03714Notably, owners are asked to determine whether histograms have outlived their
Caitlin Fischerb5e94352020-10-27 17:34:50715usefulness. When a histogram is nearing expiry, a robot files a reminder bug in
716Monorail. It's important that somebody familiar with the histogram notices and
717triages such bugs!
rkaplow8a62ef62016-10-06 14:42:34718
Ilya Shermanf64bca252020-11-10 23:16:24719Tip: When removing someone from the owner list for a histogram, it's a nice
720courtesy to ask them for approval.
721
Caitlin Fischerfeafb4392020-10-05 21:10:07722### Components
723
Ariel Zhang62ee3f42024-02-26 23:25:29724Histograms may be associated with a component, which can help make sure that
Caitlin Fischerfeafb4392020-10-05 21:10:07725histogram expiry bugs don't fall through the cracks.
726
Ariel Zhang62ee3f42024-02-26 23:25:29727A histogram is associated with the `buganizer_public` component listed in the
728DIR_METADATA file adjacent to the histograms.xml file if present.
729
730There are two other ways in which components may be associated with a
731histogram. The first way is to add a tag containing the component ID to a
732histogram or histogram suffix, e.g. <component>1456399</component>. The second
733way is to specify an OWNERS file as a secondary owner for a histogram. If the
734OWNERS file has an adjacent DIR_METADATA file that contains a
735`buganizer_public` component, then that component is associated with the
736histogram. If there isn't a parallel DIR_METADATA file with such a component,
737but an ancestor directory has one, then the ancestor directory's component is
738used.
739
740If more than one component is associated with a histogram, <component> tag is
741favored over adjacent DIR_METADATA file and over OWNERS file.
742
743**Note:** For non-Chromium Issue Tracker (ChromeOS Public Tracker or internal)
744components, make sure [email protected] has access to create and
745update issues.
746
Caitlin Fischerfeafb4392020-10-05 21:10:07747
Sun Yueru39385712023-02-09 20:11:08748### Improvement Direction
749For some histograms, an increase or a decrease in the reported values can be
750associated with either an improvement or a deterioration. For example, if you
751are tracking page load speed, then seeing your metrics tracking page load time
752in milliseconds getting gradually larger values, perhaps as the result of a
753Finch study, may signify worse performance; on the contrary, seeing a reduction
754in the page load speed may indicate an improvement. You can provide this
755information on the movement direction by adding a tag
756 `<improvement direction="LOWER_IS_BETTER"/>` within your `<histogram>`. The
757opposite is `<improvement direction="HIGHER_IS_BETTER"/>`.
758
759For other histograms where there may not be a movement direction that's clearly
760better, you can set `<improvement direction="NEITHER_IS_BETTER"/>`.
761
762This `<improvement>` tag is optional. You can also add/delete this tag or make a
763correction to its `direction` attribute any time.
764
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33765### Cleaning Up Histogram Entries {#obsolete}
mpearson2b5f7e02016-10-03 21:27:03766
Alexei Svitkine7bfb6702023-11-28 18:18:24767When the code to log a histogram is deleted, its corresponding histograms.xml
768entry should also be removed. Past histogram data will still be available for
769viewing on Google's internal UMA dashboard.
Pavol Marko17ed24e2023-09-11 09:43:15770
Alexei Svitkine7bfb6702023-11-28 18:18:24771The CL to remove one or more histograms can also specify an obsoletion message
772through special syntax in the CL description. This also applies to variants of a
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33773[patterned histogram](#Patterned-Histograms) and to suffix entries for a
774suffixed histogram.
Mark Pearson2a311c52019-03-19 21:47:01775
Ariel Zhanged17ef22023-05-18 16:42:48776The changelist that obsoletes a histogram entry should be reviewed by all
777current owners.
Mark Pearson2a311c52019-03-19 21:47:01778
Ariel Zhanged17ef22023-05-18 16:42:48779#### Remove the Entry
Mark Pearson2a311c52019-03-19 21:47:01780
Ariel Zhanged17ef22023-05-18 16:42:48781Delete the entry in the histograms.xml file.
Gabriel Gauthier-Shalom0c0f1d862022-02-09 15:47:33782
Gabriel Gauthier-Shaloma7394aa2022-02-14 16:33:37783* In some cases there may be artifacts that remain, with some examples being:
Charlie Harrison1ad2f852023-11-06 18:22:23784 * Empty `<token>` blocks, or individual `<variant>`s.
Gabriel Gauthier-Shaloma7394aa2022-02-14 16:33:37785 * `<enum>` blocks from enums.xml that are no longer used.
Alexei Svitkine7bfb6702023-11-28 18:18:24786 * Suffix entries in `histogram_suffixes_list.xml`.
Gabriel Gauthier-Shaloma7394aa2022-02-14 16:33:37787* Please remove these artifacts if you find them.
Sun Yueruf81cee32023-01-19 01:52:58788 * **Exception**: please update the label of `<int value=... label=... />` with
789 the `(Obsolete) ` prefix, e.g.
790 `<int value="1" label="(Obsolete) Navigation failed. Removed in 2023/01."/>`
791 rather than deleting them, if the surrounding `<enum>` block is not being
792 deleted.
Ariel Zhanged17ef22023-05-18 16:42:48793
794#### Add an Obsoletion Message
795
Will Harris0874e552023-08-25 16:09:44796An obsoletion message is displayed on the dashboard and provides developers
797context for why the histogram was removed and, if applicable, which histogram
798it was replaced by.
799
Alexei Svitkine7bfb6702023-11-28 18:18:24800**Note:** You can skip this step if the histogram is expired. This is because
801tooling automatically records the date and milestone of a histogram's
Ariel Zhangd111b722023-12-12 15:48:58802removal.
Ariel Zhang1cd268202023-07-14 19:30:56803
Will Harris0874e552023-08-25 16:09:44804You can provide a custom obsoletion message for a removed histogram via tags
805on the CL description:
Ariel Zhanged17ef22023-05-18 16:42:48806
807* Add the obsoletion message in the CL description in the format
Alexei Svitkine7bfb6702023-11-28 18:18:24808 `OBSOLETE_HISTOGRAM[histogram name]=message`, e.g.:
809 `OBSOLETE_HISTOGRAM[Tab.Count]=Replaced by Tab.Count2`
810* To add the same obsoletion message to all the histograms removed in the CL,
811 you can use `OBSOLETE_HISTOGRAMS=message`, e.g.:
812 `OBSOLETE_HISTOGRAMS=Patterned histogram Hist.{Token} is replaced by Hist.{Token}.2`
Ariel Zhang7b8cbf92023-06-21 22:24:14813* **Notes:**
Ariel Zhangd111b722023-12-12 15:48:58814 * **The full tag should be put on a single line, even if it is longer than the
815 maximum CL description width.**
Ariel Zhang1cd268202023-07-14 19:30:56816 * You can add multiple obsoletion message tags in one CL.
Alexei Svitkine7bfb6702023-11-28 18:18:24817 * `OBSOLETE_HISTOGRAMS` messages will be overwritten by histogram-specific
818 ones, if present.
819* You could also include information about why the histogram was removed. For
820 example, you might indicate how the histogram's summary did not accurately
821 describe the collected data.
822* If the histogram is being replaced, include the name of the replacement and
823 make sure that the new description is different from the original to reflect
824 the change between versions.
Ilya Sherman8f0034a2020-07-22 22:06:34825
Ilya Sherman9e22dea2020-10-05 22:32:36826### Patterned Histograms
Ilya Shermanf54104b2017-07-12 23:45:47827
828It is sometimes useful to record several closely related metrics, which measure
Ilya Sherman9e22dea2020-10-05 22:32:36829the same type of data, with some minor variations. You can declare the metadata
830for these concisely using patterned histograms. For example:
Ilya Shermanf54104b2017-07-12 23:45:47831
Ilya Sherman9e22dea2020-10-05 22:32:36832```xml
Jared Saul73a9daaf2021-05-04 15:33:02833<histogram name="Pokemon.{Character}.EfficacyAgainst{OpponentType}"
Robert Kaplowe1430ce2021-03-25 19:02:18834 units="multiplier" expires_after="M95">
Ilya Sherman9e22dea2020-10-05 22:32:36835 <owner>[email protected]</owner>
836 <owner>[email protected]</owner>
837 <summary>
838 The efficacy multiplier for {Character} against an opponent of
839 {OpponentType} type.
840 </summary>
841 <token key="Character">
842 <variant name="Bulbasaur"/>
843 <variant name="Charizard"/>
844 <variant name="Mewtwo"/>
845 </token>
846 <token key="OpponentType">
847 <variant name="Dragon" summary="dragon"/>
848 <variant name="Flying" summary="flappity-flap"/>
849 <variant name="Psychic" summary="psychic"/>
850 <variant name="Water" summary="water"/>
851 </token>
852</histogram>
853```
854
855This example defines metadata for 12 (= 3 x 4) concrete histograms, such as
856
857```xml
Robert Kaplowe1430ce2021-03-25 19:02:18858<histogram name="Pokemon.Charizard.EfficacyAgainstWater"
859 units="multiplier" expires_after="M95">
Ilya Sherman9e22dea2020-10-05 22:32:36860 <owner>[email protected]</owner>
861 <owner>[email protected]</owner>
862 <summary>
863 The efficacy multiplier for Charizard against an opponent of water type.
864 </summary>
865</histogram>
866```
867
James Lee53e80dc2024-04-19 11:31:06868Each token `<variant>` defines what text should be substituted for it,
869both in the histogram name and in the summary text. The name part gets
870substituted into the histogram name; the summary part gets substituted in
Mark Pearson268ea6b2021-09-28 00:44:45871the summary field (the histogram description). As shorthand, a
872`<variant>` that omits the `summary` attribute substitutes the value of
873the `name` attribute in the histogram's `<summary>` text as well.
Ilya Sherman9e22dea2020-10-05 22:32:36874
875*** promo
876Tip: You can declare an optional token by listing an empty name: `<variant
877name="" summary="aggregated across all breakdowns"/>`. This can be useful when
878recording a "parent" histogram that aggregates across a set of breakdowns.
879***
880
881You can use the `<variants>` tag to define a set of `<variant>`s out-of-line.
882This is useful for token substitutions that are shared among multiple families
Ariel Zhang6adadaf2023-06-07 14:55:15883of histograms within the same file. See
Ilya Sherman9e22dea2020-10-05 22:32:36884[histograms.xml](https://source.chromium.org/search?q=file:histograms.xml%20%3Cvariants)
885for examples.
886
Joe Masonb468cc42022-06-21 18:02:16887*** promo
888Warning: The `name` attribute of the `<variants>` tag is globally scoped, so
Ariel Zhang6adadaf2023-06-07 14:55:15889use detailed names to avoid collisions. The `<variants>` defined should only
890be used within the file.
Joe Masonb468cc42022-06-21 18:02:16891***
892
Caitlin Fischerb5e94352020-10-27 17:34:50893By default, a `<variant>` inherits the owners declared for the patterned
Ilya Sherman9e22dea2020-10-05 22:32:36894histogram. Each variant can optionally override the inherited list with custom
895owners:
896```xml
897<variant name="SubteamBreakdown" ...>
898 <owner>[email protected]</owner>
899 <owner>[email protected]</owner>
900</variant>
901```
Mark Pearsona0109122018-05-30 18:23:05902
Ilya Sherman9e22dea2020-10-05 22:32:36903*** promo
Oksana Zhuravlova5242ad22021-02-19 00:14:20904Tip: You can run `print_expanded_histograms.py --pattern=` to show all generated
Weilun Shibac61d9d32020-11-12 02:40:26905histograms by patterned histograms or histogram suffixes including their
906summaries and owners. For example, this can be run (from the repo root) as:
907```
Oksana Zhuravlova5242ad22021-02-19 00:14:20908./tools/metrics/histograms/print_expanded_histograms.py --pattern=^UMA.A.B
Weilun Shibac61d9d32020-11-12 02:40:26909```
910***
911
912*** promo
Ilya Sherman9e22dea2020-10-05 22:32:36913Tip: You can run `print_histogram_names.py --diff` to enumerate all the
914histogram names that are generated by a particular CL. For example, this can be
915run (from the repo root) as:
Charlie Harrison90407d92020-05-19 23:57:32916```
Egor Pasko5ec32b72021-07-23 14:34:22917./tools/metrics/histograms/print_histogram_names.py --diff origin/main
Charlie Harrison90407d92020-05-19 23:57:32918```
Ilya Sherman9e22dea2020-10-05 22:32:36919***
920
921For documentation about the `<histogram_suffixes>` syntax, which is deprecated,
922see
923https://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:32924
mpearson2b5f7e02016-10-03 21:27:03925## When To Use Sparse Histograms
926
Caitlin Fischerb5e94352020-10-27 17:34:50927Sparse histograms are well-suited for recording counts of exact sample values
928that are sparsely distributed over a large range. They can be used with enums
Ilya Sherman1eee82c4c2017-12-08 01:22:19929as well as regular integer values. It is often valuable to provide labels in
930[enums.xml](./enums.xml).
mpearson2b5f7e02016-10-03 21:27:03931
932The implementation uses a lock and a map, whereas other histogram types use a
933vector and no lock. It is thus more costly to add values to, and each value
934stored has more overhead, compared to the other histogram types. However it
935may be more efficient in memory if the total number of sample values is small
936compared to the range of their values.
937
Mark Pearsoned73f1f2019-03-22 18:00:12938Please talk with the metrics team if there are more than a thousand possible
939different values that you could emit.
940
rkaplow6dfcb892016-10-04 14:04:27941For more information, see [sparse_histograms.h](https://cs.chromium.org/chromium/src/base/metrics/sparse_histogram.h).
Caitlin Fischerb466a042019-07-31 21:41:46942
Ilya Shermanf64bca252020-11-10 23:16:24943
Robert Kaplow6be6fbf2021-04-19 17:30:38944# Becoming a Metrics Reviewer
Caitlin Fischerb466a042019-07-31 21:41:46945
Jared Saul73a9daaf2021-05-04 15:33:02946Any Chromium committer who is also a Google employee is eligible to become a
947metrics reviewer. Please follow the instructions at [go/reviewing-metrics](https://goto.google.com/reviewing-metrics).
948This consists of reviewing our training materials and passing an informational
949quiz. Since metrics have a direct impact on internal systems and have privacy
Robert Kaplow6be6fbf2021-04-19 17:30:38950considerations, we're currently only adding Googlers into this program.
951
952
953# Reviewing Metrics CLs
Ilya Shermanf64bca252020-11-10 23:16:24954
Robert Kaplowcbc6fd62021-03-19 15:11:40955If you are a metric OWNER, you have the serious responsibility of ensuring
956Chrome's data collection is following best practices. If there's any concern
957about an incoming metrics changelist, please escalate by assigning to
958[email protected].
959
Ilya Shermanf64bca252020-11-10 23:16:24960When reviewing metrics CLs, look at the following, listed in approximate order
961of importance:
962
Robert Kaplow6be6fbf2021-04-19 17:30:38963## Privacy
Ilya Shermanf64bca252020-11-10 23:16:24964
965Does anything tickle your privacy senses? (Googlers, see
966[go/uma-privacy](https://goto.google.com/uma-privacy) for guidelines.)
967
968**Please escalate if there's any doubt!**
969
Robert Kaplow6be6fbf2021-04-19 17:30:38970## Clarity
Ilya Shermanf64bca252020-11-10 23:16:24971
972Is the metadata clear enough for [all Chromies](#Understandable-to-Everyone) to
973understand what the metric is recording? Consider the histogram name,
974description, units, enum labels, etc.
975
976It's really common for developers to forget to list [when the metric is
977recorded](#State-When-It-Is-Recorded). This is particularly important context,
978so please remind developers to clearly document it.
979
980Note: Clarity is a bit less important for very niche metrics used only by a
981couple of engineers. However, it's hard to assess the metric design and
982correctness if the metadata is especially unclear.
983
Robert Kaplow6be6fbf2021-04-19 17:30:38984## Metric design
Ilya Shermanf64bca252020-11-10 23:16:24985
986* Does the metric definition make sense?
987* Will the resulting data be interpretable at analysis time?
988
Robert Kaplow6be6fbf2021-04-19 17:30:38989## Correctness
Ilya Shermanf64bca252020-11-10 23:16:24990
991Is the histogram being recorded correctly?
992
993* Does the bucket layout look reasonable?
994
995 * The metrics APIs like base::UmaHistogram* have some sharp edges,
996 especially for the APIs that require specifying the number of
997 buckets. Check for off-by-one errors and unused buckets.
998
999 * Is the bucket layout efficient? Typically, push back if there are >50
1000 buckets -- this can be ok in some cases, but make sure that the CL author
1001 has consciously considered the tradeoffs here and is making a reasonable
1002 choice.
1003
1004 * For timing metrics, do the min and max bounds make sense for the duration
1005 that is being measured?
1006
1007* The base::UmaHistogram* functions are
1008 [generally preferred](#Coding-Emitting-to-Histograms) over the
1009 UMA_HISTOGRAM_* macros. If using the macros, remember that names must be
1010 runtime constants!
1011
1012Also, related to [clarity](#Clarity): Does the client logic correctly implement
1013the metric described in the XML metadata? Some common errors to watch out for:
1014
1015* The metric is only emitted within an if-stmt (e.g., only if some data is
1016 available) and this restriction isn't mentioned in the metadata description.
1017
1018* The metric description states that it's recorded when X happens, but it's
1019 actually recorded when X is scheduled to occur, or only emitted when X
1020 succeeds (but omitted on failure), etc.
1021
1022When the metadata and the client logic do not match, the appropriate solution
1023might be to update the metadata, or it might be to update the client
1024logic. Guide this decision by considering what data will be more easily
1025interpretable and what data will have hidden surprises/gotchas.
1026
Robert Kaplow6be6fbf2021-04-19 17:30:381027## Sustainability
Ilya Shermanf64bca252020-11-10 23:16:241028
Robert Kaplowcd6e0422021-04-07 21:58:531029* Is the CL adding a reasonable number of metrics/buckets?
Ilya Shermanf64bca252020-11-10 23:16:241030 * When reviewing a CL that is trying to add many metrics at once, guide the CL
1031 author toward an appropriate solution for their needs. For example,
1032 multidimensional metrics can be recorded via UKM, and we are currently
Robert Kaplowcd6e0422021-04-07 21:58:531033 building support for structured metrics in UMA.
1034 * There's no hard rule, but anything above 20 separate histograms should be
1035 escalated by being assigned to [email protected].
1036 * Similarly, any histogram with more than 100 possible buckets should be
1037 escalated by being assigned to [email protected].
Ilya Shermanf64bca252020-11-10 23:16:241038
1039* Are expiry dates being set
Victor Hugo Vianna Silvaf27d8387c2024-06-11 14:19:191040 [appropriately](#How-to-choose-expiry-for-new-histograms)?
Ilya Shermanf64bca252020-11-10 23:16:241041
Robert Kaplow6be6fbf2021-04-19 17:30:381042## Everything Else!
Ilya Shermanf64bca252020-11-10 23:16:241043
1044This document describes many other nuances that are important for defining and
1045recording useful metrics. Check CLs for these other types of issues as well.
1046
1047And, as you would with a language style guide, periodically re-review the doc to
1048stay up to date on the details.
1049
Ilya Shermanf64bca252020-11-10 23:16:241050
Robert Kaplow6be6fbf2021-04-19 17:30:381051# Team Documentation
Ilya Shermanf64bca252020-11-10 23:16:241052
Caitlin Fischerb466a042019-07-31 21:41:461053
1054## Processing histograms.xml
1055
1056When working with histograms.xml, verify whether you require fully expanded
1057OWNERS files. Many scripts in this directory process histograms.xml, and
1058sometimes OWNERS file paths are expanded and other times they are not. OWNERS
1059paths are expanded when scripts make use of merge_xml's function MergeFiles;
1060otherwise, they are not.