1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
|
.. _userinteractionstelemetry:
=================
User Interactions
=================
The Background Hang Reporter is a tool that collects stacks during hangs on pre-release channels.
User Interactions are a way of annotating Background Hang Reports with additional information about what the user was doing when a hang occurs.
This allows for grouping and prioritization of hangs based on the user interactions that they occur during.
Since the built-in profiler is often the first tool that developers reach for to debug performance issues,
User Interactions also will add profiler markers for each recording.
.. important::
Every new or changed data collection in Firefox needs a `data collection review <https://wiki.mozilla.org/Firefox/Data_Collection>`__ from a Data Steward.
.. _userinteractionsserializationformat:
Serialization format
====================
User Interactions are submitted in a :doc:`../data/backgroundhangmonitor-ping` as a property under the `annotations` for a hang, e.g.:
.. code-block:: js
...
{
"duration": 105.547582,
// ...
"annotations": [
["UserInteracting", "true"]
["browser.tabs.opening", "animated"]
],
"stack": [
"XREMain::XRE_main",
"-[GeckoNSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]",
"nsAppShell::ProcessGeckoEvents",
"nsRefreshDriver::Tick",
"EventDispatcher::Dispatch",
"EventDispatcher::Dispatch",
"",
"browser/content/tabbrowser-tabs.js:1699",
"browser/content/tabbrowser-tabs.js:1725",
"browser/content/tabbrowser-tabs.js:142",
"browser/content/tabbrowser-tabs.js:153",
"(jit frame)",
"(unresolved)",
[
1,
"418de17"
],
[
1,
"418de91"
],
[
1,
"4382e56"
],
[
8,
"108e3"
],
[
9,
"2624"
],
[
9,
"129f"
]
]
// ...
},
Each User Interaction is of the form:
.. code-block:: js
["User Interaction ID", "value"]
A `User Interaction ID` is its category concatenated with its name.
For example, a User Interaction with category `browser.tabs` and name `opening` has an ID of `browser.tabs.opening`.
.. _userinteractionslimits:
Limits
------
Each ``String`` marked as an identifier (the User Interaction ``name``, ``category``, ``value``) is restricted to be composed of alphanumeric ASCII characters ([a-zA-Z0-9]) plus infix underscores ('_' characters that aren't the first or last).
``category`` is also permitted infix periods ('.' characters, so long as they aren't the first or last character).
Several fields are subject to length limits:
- ``category``: Max. byte length is ``40``.
- ``User Interaction`` name: Max. byte length is ``40``.
- ``value``: A UTF-8 string with max. byte length of ``50``.
Any ``String`` going over its limit will be reported as an error and the operation aborted.
.. _userinteractionsdefinition:
The YAML definition file
========================
Any User Interaction recorded into Firefox Telemetry must be registered before it can be recorded.
For any code that ships as part of Firefox that happens in `UserInteractions.yaml <https://dxr.mozilla.org/mozilla-central/source/toolkit/components/telemetry/UserInteractions.yaml>`_.
The User Interactions in the definition file are represented in a fixed-depth, three-level structure.
The first level contains *category* names (grouping multiple User Interactions together),
the second level contains User Interaction IDs, under which the User Interaction properties are listed. E.g.:
.. code-block:: yaml
# The following is a category of User Interactions named "browser.tabs".
browser.tabs:
opening: # This is the name of the User Interaction. The ID for the
# User Interaction is browser.tabs.opening
description: >
Describes this User Interaction in detail, potentially over
multiple lines.
# ... and more User Interaction properties.
# ... and more User Interactions.
# This is the "browser.places" category.
browser.places:
# And the "history" search User Interaction. Its User Interaction ID is
# browser.places.history_async
history_async:
# ...
description: Session History is searched asynchronously.
# ... and more User Interaction properties.
# ...
Category and User Interaction names are subject to the limits :ref:`specified above <userinteractionslimits>`.
Profiler markers
================
The profiler markers automatically added for each User Interaction will have a starting point and ending point corresponding with the recording of the User Interaction.
The name of the marker will be the User Interaction category plus the User Interaction ID.
The value of the marker will be the value passed through the `UserInteraction` API, plus any additional text that is optionally added when the recording is finished.
Further details on what the profiler is and what profiler markers are can be found `here <https://profiler.firefox.com/docs/#/>`_.
The API
=======
Public JS API
-------------
This API is main-thread only, and all functions will return `false` if accessed off of the main thread.
``start()``
~~~~~~~~~~~~~~~~~
.. code-block:: js
UserInteraction.start(id, value, object);
Starts recording a User Interaction.
Any hangs that occur on the main thread while recording this User Interaction result in an annotation being added to the background hang report.
If a pre-existing UserInteraction already exists with the same ``id`` and the same ``object``, that pre-existing UserInteraction will be overwritten.
The newly created UserInteraction will include a "(clobbered)" suffix on its BHR annotation name.
* ``id``: Required. A string value, limited to 80 characters. This is the category name concatenated with the User Interaction name.
* ``value``: Required. A string value, limited to 50 characters.
* ``object``: Optional. If specified, the User Interaction is associated with this object, so multiple recordings can be done concurrently.
Example:
.. code-block:: js
UserInteraction.start("browser.tabs.opening", "animated", window1);
UserInteraction.start("browser.tabs.opening", "animated", window2);
Returns `false` and logs a message to the browser console if the recording does not start for some reason.
Example:
.. code-block:: js
UserInteraction.start("browser.tabs.opening", "animated", window);
UserInteraction.start("browser.places.history_search", "synchronous");
``update()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: js
UserInteraction.update(id, value, object);
Updates a User Interaction that's already being recorded with a new value.
Any hangs that occur on the main thread will be annotated using the new value.
Updating only works for User Interactions that are already being recorded.
* ``id``: Required. A string value, limited to 80 characters. This is the category name concatenated with the User Interaction name.
* ``value``: Required. The new string value, limited to 50 characters.
* ``object``: Optional. If specified, the User Interaction is associated with this object, so multiple recordings can be done concurrently.
Returns `false` and logs a message to the browser console if the update cannot be done for some reason.
Example:
.. code-block:: js
// At this point, we don't know if the tab will open with animation
// or not.
UserInteraction.start("browser.tabs.opening", "initting", window);
// ...
if (animating) {
UserInteraction.update("browser.tabs.opening", "animating", window);
} else {
UserInteraction.update("browser.tabs.opening", "not-animating", window);
}
``cancel()``
~~~~~~~~~~~~~~~~~~~~
.. code-block:: js
UserInteraction.cancel(id, object);
Cancels a recording User Interaction.
No profiler marker will be added in this case, and no further hangs will be annotated.
Hangs that occurred before the User Interaction was cancelled will not, however, be expunged.
* ``id``: Required. A string value, limited to 80 characters. This is the category name concatenated with the User Interaction name.
* ``object``: Optional. If specified, the User Interaction is associated with this object, so multiple recordings can be done concurrently.
Returns `false` and logs a message to the browser console if the cancellation cannot be completed for some reason.
``running()``
~~~~~~~~~~~~~~~~~~~~
.. code-block:: js
UserInteraction.running(id, object);
Checks to see if a UserInteraction is already running.
* ``id``: Required. A string value, limited to 80 characters. This is the category name concatenated with the User Interaction name.
* ``object``: Optional. If specified, the User Interaction is associated with this object, so multiple recordings can be done concurrently. If you're checking for a running timer that was started with an object, you'll need to pass in that same object here to check its running state.
Returns `true` if a UserInteraction is already running.
``finish()``
~~~~~~~~~~~~~~~~~~~~
.. code-block:: js
UserInteraction.finish(id, object, additionalText);
Finishes recording the User Interaction.
Any hangs that occur on the main thread will no longer be annotated with this User Interaction.
A profiler marker will also be added, starting at the `UserInteraction.start` point and ending at the `UserInteraction.finish` point, along with any additional text that the author wants to include.
* ``id``: Required. A string value, limited to 80 characters. This is the category name concatenated with the User Interaction name.
* ``object``: Optional. If specified, the User Interaction is associated with this object, so multiple recordings can be done concurrently.
* ``additionalText``: Optional. If specified, the profile marker will have this text appended to the `value`, separated with a comma.
Returns `false` and logs a message to the browser console if finishing cannot be completed for some reason.
Version History
===============
- Firefox 84: Initial User Interaction support (see `bug 1661304 <https://bugzilla.mozilla.org/show_bug.cgi?id=1661304>`__).
|