Labeled Timing Distributions
Labeled timing distributions are used to record different related distributions of time measurements.
See the Timing Distribution reference for details on bucket distribution, specifics about how Glean records time, and a histogram simulator.
Recording API
start
Start tracking time for the provided metric for the given label. Multiple timers for multiple labels can run simultaneously.
Returns a unique TimerId
for the new timer.
use glean_metrics::devtools;
self.start = devtools::cold_toolbox_open_delay
.get(toolbox_id)
.start();
C++
#include "mozilla/glean/GleanMetrics.h"
auto timerId = mozilla::glean::devtools::cold_toolbox_open_delay
.Get(toolbox_id)
.Start();
JavaScript
const timerId = Glean.devtools.coldToolboxOpenDelay[toolbox_id].start();
Recorded Errors
invalid_label
:- If the label contains invalid characters. Data is still recorded to the special label
__other__
. - If the label exceeds the maximum number of allowed characters. Data is still recorded to the special label
__other__
.
- If the label contains invalid characters. Data is still recorded to the special label
stopAndAccumulate
Stops tracking time for the provided timer from the metric for the given label.
Adds a count to the corresponding bucket in the label's timing distribution.
Do not use the provided TimerId
after passing it to this method.
use glean_metrics::devtools;
devtools::cold_toolbox_open_delay
.get(toolbox_id)
.stop_and_accumulate(self.start);
C++
#include "mozilla/glean/GleanMetrics.h"
mozilla::glean::devtools::cold_toolbox_open_delay
.Get(toolbox_id)
.StopAndAccumulate(std::move(timerId));
JavaScript
Glean.devtools.coldToolboxOpenDelay[toolbox_id].stopAndAccumulate(timerId);
Recorded errors
invalid_state
: If a non-existing, cancelled, or already-stopped timer is stopped again.invalid_label
:- If the label contains invalid characters. Data is still recorded to the special label
__other__
. - If the label exceeds the maximum number of allowed characters. Data is still recorded to the special label
__other__
.
- If the label contains invalid characters. Data is still recorded to the special label
cancel
Aborts a previous start
call, consuming the supplied timer id.
use glean_metrics::devtools;
devtools::cold_toolbox_open_delay
.get(toolbox_id)
.cancel(self.start);
C++
#include "mozilla/glean/GleanMetrics.h"
mozilla::glean::devtools::cold_toolbox_open_delay
.Get(toolbox_id)
.Cancel(std::move(timerId));
JavaScript
Glean.devtools.coldToolboxOpenDelay[toolbox_id].cancel(timerId);
Recorded errors
invalid_label
:- If the label contains invalid characters. Data is still recorded to the special label
__other__
. - If the label exceeds the maximum number of allowed characters. Data is still recorded to the special label
__other__
.
- If the label contains invalid characters. Data is still recorded to the special label
accumulateSamples
Accumulates the provided, signed samples in the metric for a given label. Where possible, have Glean do the timing for you and don't use methods like this one. If you are doing timing yourself, ensure your time source is monotonic and behaves consistently across platforms.
This is required so that the platform-specific code can provide us with
64 bit signed integers if no u64
comparable type is available. This
will take care of filtering and reporting errors for any provided negative
sample.
Please note that this assumes that the provided samples are already in
the "unit" declared by the instance of the metric type (e.g. if the
instance this method was called on is using TimeUnit::Second
, then
samples
are assumed to be in that unit).
use glean_metrics::devtools;
devtools::cold_toolbox_open_delay
.get(toolbox_id)
.accumulate_samples(samples);
C++
#include "mozilla/glean/GleanMetrics.h"
mozilla::glean::devtools::cold_toolbox_open_delay
.Get(toolbox_id)
.AccumulateRawSamples(samples);
JavaScript
This operation is not currently supported in JavaScript.
Recorded errors
invalid_value
: If recording a negative sample.invalid_overflow
: If recording a sample longer than the maximum for the giventime_unit
.invalid_label
:- If the label contains invalid characters. Data is still recorded to the special label
__other__
. - If the label exceeds the maximum number of allowed characters. Data is still recorded to the special label
__other__
.
- If the label contains invalid characters. Data is still recorded to the special label
accumulateSingleSample
Accumulates a single signed sample and appends it to the metric for the provided label.
Prefer start()
and stopAndAccumulate()
where possible,
but if you must record time externally please prefer this method for individual samples
(avoids having to allocate and pass collections).
A signed value is required so that the platform-specific code can provide
us with a 64 bit signed integer if no u64
comparable type is available.
This will take care of filtering and reporting errors for a negative
sample.
Please note that this assumes that the provided sample is already in
the "unit" declared by the instance of the metric type (e.g. if the
instance this method was called on is using TimeUnit::Second
, then
sample
is assumed to be in that unit).
use glean_metrics::devtools;
devtools::cold_toolbox_open_delay
.get(toolbox_id)
.accumulate_single_sample(sample);
C++
#include "mozilla/glean/GleanMetrics.h"
mozilla::glean::devtools::cold_toolbox_open_delay
.Get(toolboxId)
.AccumulateRawDuration(aDuration);
JavaScript
This operation is not currently supported in JavaScript.
Recorded errors
invalid_value
: If recording a negative sample.invalid_overflow
: If recording a sample longer than the maximum for the giventime_unit
.invalid_label
:- If the label contains invalid characters. Data is still recorded to the special label
__other__
. - If the label exceeds the maximum number of allowed characters. Data is still recorded to the special label
__other__
.
- If the label contains invalid characters. Data is still recorded to the special label
Testing API
testGetValue
Gets the recorded value for a given label in a labeled timing distribution metric.
Returns a struct with counts per buckets and total sum if data is stored.
Returns a language-specific empty/null value if no data is stored.
Has an optional argument to specify the name of the ping you wish to retrieve data from, except
in Rust where it's required. None
or no argument will default to the first value found for send_in_pings
.
use glean_metrics::devtools;
// Get the current snapshot of stored values.
let snapshot = devtools::cold_toolbox_open_delay.get("webconsole").test_get_value(None).unwrap();
// Usually you don't know the exact timing values,
// but you do know how many samples there are:
assert_eq!(2, snapshot.count);
// ...and the lower bound of how long they all took:
assert_ge!(400, snapshot.sum);
C++
#include "mozilla/glean/GleanMetrics.h"
const data = mozilla::glean::devtools::cold_toolbox_open_delay
.Get("webconsole"_ns)
.TestGetValue().value().unwrap();
ASSERT_TRUE(data.sum > 0);
JavaScript
Assert.ok(Glean.devtools.coldToolboxOpenDelay["webconsole"].testGetValue().sum > 0);
testGetNumRecordedErrors
Gets the number of errors recorded for a given labeled timing distribution metric in total.
use glean::ErrorType;
use glean_metrics::network;
// Assert there were no negative values instrumented.
assert_eq!(
0,
devtools::cold_toolbox_open_delay.test_get_num_recorded_errors(
ErrorType::InvalidValue,
None
)
);
Metric parameters
Example labeled timing distribution metric definition:
devtools:
cold_toolbox_open_delay:
type: labeled_timing_distribution
description: >
Time taken to open the first DevTools toolbox, per tool being opened.
time_unit: millisecond
bugs:
- https://bugzilla.mozilla.org/000000
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=000000#c3
notification_emails:
- me@mozilla.com
expires: 175
labels:
- inspector
- webconsole
- jsdebugger
...
Extra metric parameters
time_unit
Labeled timing distributions have an optional time_unit
parameter to specify the smallest unit of resolution that it will record.
The allowed values for time_unit
are:
nanosecond
(default)microsecond
millisecond
second
minute
hour
day
labels
Labeled metrics may have an optional labels
parameter, containing a list of known labels.
The labels in this list must match the following requirements:
- Conform to the label format.
- Each label must have a maximum of 71 characters.
- Each label must only contain printable ASCII characters.
- This list itself is limited to 100 labels.
Important
If the labels are specified in the
metrics.yaml
, using any label not listed in that file will be replaced with the special value__other__
.If the labels are not specified in the
metrics.yaml
, only 16 different dynamic labels may be used, after which the special value__other__
will be used.
Removing or changing labels, including their order in the registry file, is permitted. Avoid reusing labels that were removed in the past. It is best practice to add documentation about removed labels to the description field so that analysts will know of their existence and meaning in historical data. Special care must be taken when changing GeckoView metrics sent through the Glean SDK, as the index of the labels is used to report Gecko data through the Glean SDK.
Data questions
- What is the distribution of initial load times of devtools toolboxes, per tool?
- What is the distribution of how long it takes to load extensions' content scripts, by addon id?
Limits
-
Timings are recorded in nanoseconds
- In Rust,
time::precise_time_ns()
is used.
- In Rust,
-
The maximum timing value that will be recorded depends on the
time_unit
parameter:nanosecond
: 1ns <= x <= 10 minutesmicrosecond
: 1μs <= x <= ~6.94 daysmillisecond
: 1ms <= x <= ~19 years
Longer times will be truncated to the maximum value and an error will be recorded.
-
Labels must conform to the label format.
-
Each label must have a maximum of 71 characters.
-
Each label must only contain printable ASCII characters.
-
The list of labels is limited to:
- 16 different dynamic labels if no static labels are defined.
Additional labels will all record to the special label
__other__
. - 100 labels if specified as static labels in
metrics.yaml
, see Labels. Unknown labels will be recorded under the special label__other__
.
- 16 different dynamic labels if no static labels are defined.
Additional labels will all record to the special label
Reference
- Rust API docs:
LabeledMetric
,TimingDistributionMetricType