# 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.

IMPORTANT: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.

## Configuration

Say you're adding a new rate for how often HTTP connections have errors.
First you need to add an entry for the rate to the `metrics.yaml`

file:

```
network:
http_connection_error:
type: rate
description: >
How many HTTP connections error out out of the total connections made.
...
```

### External Denominators

If several rates share the same denominator
(from our example above, maybe there are multiple rates per total connections made)
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
...
```

## API

Since a rate is two numbers, you add to each one individually:

`#![allow(unused)] fn main() { use glean_metrics::*; if connection_had_error { network::http_connection_error.add_to_numerator(1); } network::http_connection_error.add_to_denominator(1); }`

If the rate uses an external denominator,
adding to the denominator must be done through the denominator's
`counter`

API:

`#![allow(unused)] fn main() { use glean_metrics; if connection_had_error { network::http_connection_error.add_to_numerator(1); } if connection_was_slow { network::http_connection_slow.add_to_numerator(1); } // network::http_connection_error has no `add_to_denominator` method. network::http_connections.add(1); }`

There are test APIs available too. Whether the rate has an external denominator or not, you can use this API to get the current value:

`#![allow(unused)] fn main() { use glean::ErrorType; use glean_metrics; // Was anything recorded? assert!(network::http_connection_error.test_get_value(None).is_some()); // Does it contain counter have the expected values? assert_eq!((1, 1), network::http_connection_error.test_get_value(None).unwrap()); // Did the numerator or denominator ever have a negative value added? assert_eq!( 0, network::http_connection_error.test_get_num_recorded_errors( ErrorType::InvalidValue ) ); }`

## 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`

).

## Examples

- How often did an HTTP connection error?
- How many documents used a given CSS Property?

## Recorded errors

`invalid_value`

: If either numerator or denominator is incremented by a negative value.