Rate
Used to count how often something happens relative to how often something else happens. Like how many documents use a particular CSS Property, or how many HTTP connections had an error. You can think of it like a fraction, with a numerator and a denominator.
All rates start without a value. A rate with a numerator of 0 is valid and will be sent to ensure we capture the "no errors happened" or "no use counted" cases.
Let the Glean metric do the counting
When using a rate metric, it is important to let the Glean metric do the counting. Using your own variable for counting and setting the metric yourself could be problematic: ping scheduling will make it difficult to ensure the metric is at the correct value at the correct time. Instead, count to the numerator and denominator as you go.
Recording API
addToNumerator
/ addToDenominator
Numerators and denominators need to be counted individually.
import org.mozilla.yourApplication.GleanMetrics.Network
if (connectionHadError) {
Network.httpConnectionError.addToNumerator(1)
}
Network.httpConnectionError.addToDenominator(1)
External Denominators
If the rate uses an external denominator,
adding to the denominator must be done through the denominator's
counter
API:
import org.mozilla.yourApplication.GleanMetrics.Network
if (connectionHadError) {
Network.httpConnectionError.addToNumerator(1)
}
Network.httpConnections.add(1)
import org.mozilla.yourApplication.GleanMetrics.Network;
if (connectionHadError) {
Network.INSTANCE.httpConnectionError().addToNumerator(1);
}
Network.IMPORTANT.httpConnectionError().addToDenominator(1);
External Denominators
If the rate uses an external denominator,
adding to the denominator must be done through the denominator's
counter
API:
import org.mozilla.yourApplication.GleanMetrics.Network;
if (connectionHadError) {
Network.INSTANCE.httpConnectionError().addToNumerator(1);
}
Network.INSTANCE.httpConnections().add(1)
if (connectionHadError) {
Network.httpConnectionError.addToNumerator(1)
}
Network.httpConnectionError.addToDenominator(1)
External Denominators
If the rate uses an external denominator,
adding to the denominator must be done through the denominator's
counter
API:
if (connectionHadError) {
Network.httpConnectionError.addToNumerator(1)
}
Network.httpConnections.add(1)
from glean import load_metrics
metrics = load_metrics("metrics.yaml")
if connection_had_error:
metrics.network.http_connection_error.add_to_numerator(1)
metrics.network.http_connection_error.add_to_denominator(1)
External Denominators
If the rate uses an external denominator,
adding to the denominator must be done through the denominator's
counter
API:
from glean import load_metrics
metrics = load_metrics("metrics.yaml")
if connection_had_error:
metrics.network.http_connection_error.add_to_numerator(1)
metrics.network.http_connections.add(1)
use glean_metrics::network;
if connection_had_error {
network::http_connection_error.add_to_numerator(1);
}
network::http_connection_error.add_to_denominator(1);
External Denominators
If the rate uses an external denominator,
adding to the denominator must be done through the denominator's
counter
API:
use glean_metrics::network;
if connection_had_error {
network::http_connection_error.add_to_numerator(1);
}
network::http_connections.add(1);
import * as network from "./path/to/generated/files/network.js";
if (connectionHadError) {
network.httpConnectionError.addToNumerator(1);
}
network.httpConnectionError.addToDenominator(1);
C++
#include "mozilla/glean/GleanMetrics.h"
if (aHadError) {
mozilla::glean::network::http_connection_error.AddToNumerator(1);
}
mozilla::glean::network::http_connection_error.AddToDenominator(1);
JavaScript
if (aHadError) {
Glean.network.httpConnectionError.addToNumerator(1);
}
Glean.network.httpConnectionError.addToDenominator(1);
Recorded errors
invalid_value
: If either numerator or denominator is incremented by a negative value.invalid_type
: If a floating point or non-number value is given.
Limits
- Numerator and Denominator only increment.
- Numerator and Denominator saturate at the largest value that can be represented as a 32-bit signed integer (
2147483647
).
Testing API
testGetValue
Gets the recorded value for a given rate metric.
Returns the numerator/denominator pair 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
.
import org.mozilla.yourApplication.GleanMetrics.Network
assertEquals(Rate(1, 1), Network.httpConnectionError.testGetValue())
import org.mozilla.yourApplication.GleanMetrics.Network;
assertEquals(Rate(1, 1), Network.INSTANCE.httpConnectionError().testGetValue());
XCTAssertEqual(
Rate(numerator: 1, denominator: 1),
Network.httpConnectionError.testGetValue()
)
from glean import load_metrics
metrics = load_metrics("metrics.yaml")
assert Rate(1, 1) == metrics.network.http_connection_error.test_get_value()
use glean_metrics::network;
let rate = network::http_connection_error.test_get_value(None).unwrap();
assert_eq!(1, rate.numerator);
assert_eq!(1, rate.denominator);
import * as network from "./path/to/generated/files/network.js";
const { numerator, denominator } = await network.httpConnectionError.testGetValue();
assert.strictEqual(numerator, 1);
assert.strictEqual(denominator, 1);
C++
#include "mozilla/glean/GleanMetrics.h"
auto pair = mozilla::glean::network::http_connection_error.TestGetValue().unwrap();
ASSERT_EQ(1, pair.first);
ASSERT_EQ(1, pair.second);
JavaScript
// testGetValue will throw NS_ERROR_LOSS_OF_SIGNIFICANT_DATA on error.
Assert.deepEqual(
{ numerator: 1, denominator: 1 },
Glean.network.httpConnectionError.testGetValue()
);
testGetNumRecordedErrors
import org.mozilla.yourApplication.GleanMetrics.Network
assertEquals(
0,
Network.httpConnectionError.testGetNumRecordedErrors(ErrorType.INVALID_VALUE)
)
import org.mozilla.yourApplication.GleanMetrics.Network;
assertEquals(
0,
Network.INSTANCE.httpConnectionError().testGetNumRecordedErrors(
ErrorType.INVALID_VALUE
)
);
XCTAssertEqual(
0,
Network.httpConnectionError.testGetNumRecordedErrors(.invalidValue)
)
from glean import load_metrics
metrics = load_metrics("metrics.yaml")
from glean.testing import ErrorType
assert 0 == metrics.network.http_connection_error.test_get_num_recorded_errors(
ErrorType.INVALID_VALUE
)
use glean::ErrorType;
use glean_metrics::network;
assert_eq!(
0,
network::http_connection_error.test_get_num_recorded_errors(
ErrorType::InvalidValue,
None
)
);
import * as network from "./path/to/generated/files/network.js";
import { ErrorType } from "@mozilla/glean/error";
assert.strictEqual(
1,
await network.httpConnectionError.testGetNumRecordedErrors(ErrorType.InvalidValue)
);
Metric parameters
Example rate metric definition:
network:
http_connection_error:
type: rate
description: >
How many HTTP connections error out out of the total connections made.
bugs:
- https://bugzilla.mozilla.org/000000
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=000000#c3
notification_emails:
- me@mozilla.com
expires: 2020-10-01
For a full reference on metrics parameters common to all metric types, refer to the metrics YAML registry format reference page.
External Denominators
If several rates share the same denominator
then the denominator should be defined as a counter
and shared between
rates
using the denominator_metric
property:
network:
http_connections:
type: counter
description: >
Total number of http connections made.
...
http_connection_error:
type: rate
description: >
How many HTTP connections error out out of the total connections made.
denominator_metric: network.http_connections
...
http_connection_slow:
type: rate
description: >
How many HTTP connections were slow, out of the total connections made.
denominator_metric: network.http_connections
...
The Glean JavaScript SDK does not support external denominators for Rate metrics, yet. Follow Bug 1745753 for updates on that features development.
Data Questions
- How often did an HTTP connection error?
- How many documents used a given CSS Property?